Bzoj 3781: 小B的询问 莫队,分块,暴力
3781: 小B的询问
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 426 Solved: 284
[Submit][Status][Discuss]
Description
小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。
Input
第一行,三个整数N、M、K。
第二行,N个整数,表示小B的序列。
接下来的M行,每行两个整数L、R。
Output
M行,每行一个整数,其中第i行的整数表示第i个询问的答案。
Sample Input
6 4 3
1 3 2 1 1 3
1 4
2 6
3 5
5 6
1 3 2 1 1 3
1 4
2 6
3 5
5 6
Sample Output
6
9
5
2
9
5
2
HINT
对于全部的数据,1<=N、M、K<=50000
Source
这道题同 小Z的袜子 。。。
只需要把 加和减 改为 加减 个数的平方 即可。。。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define MAXN 50010 5 struct node 6 { 7 int l,r,id; 8 }q[MAXN]; 9 LL ans[MAXN]; 10 int C[MAXN],pos[MAXN],tot[MAXN]; 11 int read() 12 { 13 int s=0,fh=1;char ch=getchar(); 14 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 15 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 16 return s*fh; 17 } 18 bool cmp(node a,node b) 19 { 20 if(pos[a.l]==pos[b.l])return a.r<b.r; 21 return a.l<b.l; 22 } 23 int main() 24 { 25 int n,m,k,block,i,L,R; 26 LL res; 27 n=read();m=read();k=read(); 28 for(i=1;i<=n;i++)C[i]=read(); 29 block=(int)sqrt(n); 30 for(i=1;i<=n;i++)pos[i]=(i-1)/block+1; 31 for(i=1;i<=m;i++) 32 { 33 q[i].l=read();q[i].r=read(); 34 q[i].id=i; 35 } 36 sort(q+1,q+m+1,cmp); 37 L=1;R=0;res=0; 38 memset(tot,0,sizeof(tot)); 39 for(i=1;i<=m;i++) 40 { 41 while(L<q[i].l) 42 { 43 res-=tot[C[L]]*tot[C[L]]; 44 tot[C[L]]--; 45 res+=tot[C[L]]*tot[C[L]]; 46 L++; 47 } 48 while(L>q[i].l) 49 { 50 L--; 51 res-=tot[C[L]]*tot[C[L]]; 52 tot[C[L]]++; 53 res+=tot[C[L]]*tot[C[L]]; 54 } 55 while(R<q[i].r) 56 { 57 R++; 58 res-=tot[C[R]]*tot[C[R]]; 59 tot[C[R]]++; 60 res+=tot[C[R]]*tot[C[R]]; 61 } 62 while(R>q[i].r) 63 { 64 res-=tot[C[R]]*tot[C[R]]; 65 tot[C[R]]--; 66 res+=tot[C[R]]*tot[C[R]]; 67 R--; 68 } 69 ans[q[i].id]=res; 70 } 71 for(i=1;i<=m;i++)printf("%lld\n",ans[i]); 72 fclose(stdin); 73 fclose(stdout); 74 return 0; 75 }