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
莫队裸题······
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 50005 7 using namespace std; 8 typedef long long int64; 9 char ch; 10 int n,m,k,a[maxn],cnt[maxn],pos[maxn],siz; 11 int64 ans[maxn],tmp; 12 struct query{ 13 int l,r,id; 14 }list[maxn]; 15 bool cmp(query a,query b){ 16 if (pos[a.l]!=pos[b.l]) return pos[a.l]<pos[b.l]; 17 return pos[a.r]<pos[b.r]; 18 } 19 bool ok; 20 void read(int &x){ 21 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 22 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 23 if (ok) x=-x; 24 } 25 void modify(int col,int op){ 26 tmp-=(1LL*cnt[col]*cnt[col]); 27 cnt[col]+=op; 28 tmp+=(1LL*cnt[col]*cnt[col]); 29 } 30 void work(){ 31 int l=1,r=0; 32 for (int i=1;i<=m;i++){ 33 for (;r<list[i].r;r++) modify(a[r+1],1); 34 for (;r>list[i].r;r--) modify(a[r],-1); 35 for (;l<list[i].l;l++) modify(a[l],-1); 36 for (;l>list[i].l;l--) modify(a[l-1],1); 37 ans[list[i].id]=tmp; 38 } 39 } 40 int main(){ 41 read(n),read(m),read(k),siz=(int)sqrt(n); 42 for (int i=1;i<=n;i++) read(a[i]); 43 for (int i=1;i<=n;i++) pos[i]=i/siz; 44 for (int i=1;i<=m;i++) read(list[i].l),read(list[i].r),list[i].id=i; 45 sort(list+1,list+m+1,cmp); 46 work(); 47 for (int i=1;i<=m;i++) printf("%lld\n",ans[i]); 48 return 0; 49 }