山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 3781 小B的询问(莫队算法)

 

【题意】

 

    若干个询问sigma{ cnt[i]^2 } cnt[i]表示i在[l,r]内的出现次数。

 

【思路】

 

    莫队算法,裸题。

    一个cnt数组即可维护插入与删除。

 

【代码】

 

 1 #include<set>
 2 #include<cmath>
 3 #include<queue>
 4 #include<vector>
 5 #include<cstdio>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
11 using namespace std;
12 
13 typedef long long ll;
14 const int N = 5e5+10;
15 
16 ll read() 
17 {
18     char c=getchar();
19     ll f=1,x=0;
20     while(!isdigit(c)) {
21         if(c=='-') f=-1; c=getchar();
22     }
23     while(isdigit(c))
24         x=x*10+c-'0',c=getchar();
25     return x*f;
26 }
27 
28 struct Node 
29 {
30     int id,pos,l,r;
31     bool operator < (const Node& rhs) const
32     {
33         return pos<rhs.pos || (pos==rhs.pos&&r<rhs.r);    
34     }
35 } q[N];
36 
37 int n,m,K,a[N]; ll ans[N],cnt[N],now;
38 
39 void upd(int x,int v)
40 {
41     now-=cnt[a[x]]*cnt[a[x]];
42     cnt[a[x]]+=v;
43     now+=cnt[a[x]]*cnt[a[x]];
44 }
45 
46 int main()
47 {
48 //    freopen("in.in","r",stdin);
49 //    freopen("out.out","w",stdout);
50     n=read(),m=read(),K=read();
51     FOR(i,1,n) a[i]=read();
52     int B=sqrt(n);
53     FOR(i,1,m) 
54     {
55         q[i].l=read(),
56         q[i].r=read();
57         q[i].id=i;
58         q[i].pos=(q[i].l-1)/B+1;
59     }
60     sort(q+1,q+m+1);
61     int l=1,r=0;
62     FOR(i,1,m)
63     {
64         while(l<q[i].l) upd(l++,-1);
65         while(l>q[i].l) upd(--l,1);
66         while(r>q[i].r) upd(r--,-1);
67         while(r<q[i].r) upd(++r,1);
68         ans[q[i].id]=now;
69     }
70     FOR(i,1,m) printf("%lld\n",ans[i]);
71     return 0;
72 }

 

posted on 2016-04-01 09:38  hahalidaxin  阅读(225)  评论(0编辑  收藏  举报