题目描述
小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。
输入输出格式
输入格式:
第一行,三个整数N、M、K。
第二行,N个整数,表示小B的序列。
接下来的M行,每行两个整数L、R。
输出格式:
M行,每行一个整数,其中第i行的整数表示第i个询问的答案。
输入输出样例
说明
对于全部的数据,1<=N、M、K<=50000
解:莫队
开一个桶记录下每个数的出现次数,然后指针在移动的时候减去原来的贡献,加上现在的贡献。
(打错一个变量名,一直一直T,┗|`O′|┛ 嗷~~,气死人)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const int N=50005; 7 int n,t[N],tot,bg[N],block,m,k,ans[N]; 8 struct query{ 9 int l,r,id; 10 }q[N]; 11 bool cmp(const query &x,const query &y) 12 { 13 if(bg[x.l]==bg[y.l]) return x.r<y.r; 14 else return bg[x.l]<bg[y.l]; 15 } 16 int L,R,a[N]; 17 int main() 18 { 19 scanf("%d%d%d",&n,&m,&k); 20 block=sqrt(n); 21 for(int i=1;i<=n;i++) 22 { 23 bg[i]=(i-1)/block+1; 24 scanf("%d",&a[i]); 25 } 26 for(int i=1;i<=m;i++) 27 scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i; 28 sort(q+1,q+m+1,cmp); 29 L=1;R=0; 30 for(int i=1;i<=m;i++) 31 { 32 while(R<q[i].r) 33 { 34 R++; 35 k=t[a[R]];t[a[R]]++; 36 tot=tot-k*k+t[a[R]]*t[a[R]]; 37 } 38 while(R>q[i].r) 39 { 40 k=t[a[R]];t[a[R]]--; 41 tot=tot-k*k+t[a[R]]*t[a[R]]; 42 R--; 43 } 44 while(L<q[i].l) 45 { 46 k=t[a[L]];t[a[L]]--; 47 tot=tot-k*k+t[a[L]]*t[a[L]]; 48 L++; 49 } 50 while(L>q[i].l) 51 { 52 L--; 53 k=t[a[L]];t[a[L]]++; 54 tot=tot-k*k+t[a[L]]*t[a[L]]; 55 } 56 ans[q[i].id]=tot; 57 } 58 for(int i=1;i<=m;i++) printf("%d\n",ans[i]); 59 return 0; 60 }
(?′?‵?)I L???????