Bzoj3781 小B的询问
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
裸莫队算法。BZOJ权限题,未评测。
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #define LL long long 8 using namespace std; 9 const int mxn=100001; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 struct line{ 17 int l,r; 18 int q; 19 int id; 20 }a[mxn]; 21 int cmp(const line a,const line b){ 22 if(a.q==b.q)return a.r<b.r; 23 return a.q<b.q; 24 } 25 int n,m,k; 26 int c[mxn]; 27 LL cnt[mxn],ans[mxn]; 28 int main(){ 29 int i,j; 30 n=read();m=read();k=read(); 31 for(i=1;i<=n;i++) c[i]=read(); 32 int size=sqrt(n);//分块 33 for(i=1;i<=m;i++){ 34 a[i].l=read(); 35 a[i].r=read(); 36 a[i].id=i; 37 a[i].q=(a[i].l-1)/size+1; 38 } 39 sort(a+1,a+m+1,cmp); 40 int l=1,r=0; 41 LL res=0; 42 for(i=1;i<=m;i++){ 43 while(l>a[i].l){ 44 l--;cnt[c[l]]++;res+=2*cnt[c[l]]-1;//相当于(n+1)*(n+1)-n*n 45 } 46 while(r<a[i].r){ 47 r++;cnt[c[r]]++;res+=2*cnt[c[r]]-1; 48 } 49 while(l<a[i].l){ 50 cnt[c[l]]--;res-=2*cnt[c[l]]+1;l++; 51 } 52 while(r>a[i].r){ 53 cnt[c[r]]--;res-=2*cnt[c[r]]+1;r--; 54 } 55 ans[a[i].id]=res; 56 } 57 for(i=1;i<=m;i++)printf("%lld\n",ans[i]); 58 return 0; 59 }
本文为博主原创文章,转载请注明出处。