Codeforces 86D - Powerful array(莫队算法)

时间:2022-02-19 19:59:27

题目链接:http://codeforces.com/problemset/problem/86/D

题目大意:给定一个数组,每次询问一个区间[l,r],设cnt[i]为数字i在该区间内的出现次数,求该区间内所有的cnt[i]^2*i。

解题思路:莫队模板题,改一下add,remove就好了。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 using namespace std;
 5 typedef long long ll;
 6 const int N=2e5+5;
 7 const int MAX=1e6+5;
 8 int  cnt[MAX],arr[N],unit;
 9 ll power,res[N];
10 
11 struct node{
12     int l,r;
13     int id;
14 }q[N];
15 
16 void add(int pos){
17     power=power+(ll)arr[pos]*(cnt[arr[pos]]<<1|1);//(a+1)*(a+1)=a*a+2*a+1;
18     cnt[arr[pos]]++;
19 }
20 
21 void remove(int pos){    
22     power=power-(ll)arr[pos]*(cnt[arr[pos]]<<1-1);
23     cnt[arr[pos]]--;
24 }
25 
26 bool cmp(node a,node b){
27     return a.l/unit!=b.l/unit?a.l/unit<b.l/unit:a.r<b.r;
28 }
29 
30 int main(){
31     int n,m;
32     scanf("%d%d",&n,&m);
33     unit=sqrt(n);
34     for(int i=1;i<=n;i++){
35         scanf("%d",&arr[i]);
36     }
37     for(int i=1;i<=m;i++){
38         scanf("%d%d",&q[i].l,&q[i].r);
39         q[i].id=i;
40     }
41     sort(q+1,q+1+m,cmp);
42     
43     int L=q[1].l,R=L-1;
44     for(int i=1;i<=m;i++){
45         while(L>q[i].l)
46             add(--L);
47         while(L<q[i].l)
48             remove(L++);
49         while(R<q[i].r)
50             add(++R);
51         while(R>q[i].r)
52             remove(R--);
53         res[q[i].id]=power;
54     }
55     for(int i=1;i<=m;i++){
56         printf("%I64d\n",res[i]);
57     } 
58 }