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
题解:裸的莫队算法吧,和小z的袜子没区别。
1 #include<cstring> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdio> 6 7 #define N 50007 8 #define ll long long 9 using namespace std; 10 inline int read() 11 { 12 int x=0,f=1;char ch=getchar(); 13 while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();} 14 while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 18 int n,m,k; 19 int a[N],sum[N],pos[N]; 20 ll ans; 21 struct Node 22 { 23 int l,r,id; 24 ll ans; 25 }res[N]; 26 27 bool cmp_id(Node x,Node y) 28 { 29 return x.id<y.id; 30 } 31 bool cmp(Node x,Node y) 32 { 33 if (pos[x.l]==pos[y.l]) return x.r<y.r; 34 else return x.l<y.l; 35 } 36 ll sqr(ll x){return x*x;} 37 void modify(int p,int z) 38 { 39 ans-=sqr(sum[a[p]]); 40 sum[a[p]]+=z; 41 ans+=sqr(sum[a[p]]); 42 } 43 void solve() 44 { 45 for (int i=1,l=1,r=0;i<=m;i++) 46 { 47 for (;r<res[i].r;r++) 48 modify(r+1,1); 49 for (;r>res[i].r;r--) 50 modify(r,-1); 51 for (;l<res[i].l;l++) 52 modify(l,-1); 53 for (;l>res[i].l;l--) 54 modify(l-1,1); 55 res[i].ans=ans; 56 } 57 } 58 int main() 59 { 60 n=read(),m=read(),k=read(); 61 int block=(int)sqrt(n); 62 for (int i=1;i<=n;i++) 63 a[i]=read(),pos[i]=(i-1)/block+1; 64 for (int i=1;i<=m;i++) 65 res[i].l=read(),res[i].r=read(),res[i].id=i; 66 sort(res+1,res+m+1,cmp); 67 solve(); 68 sort(res+1,res+m+1,cmp_id); 69 for (int i=1;i<=m;i++) 70 printf("%lld\n",res[i].ans); 71 }