bzoj3781小B的询问*

bzoj3781小B的询问

题意:

给定一个长度为n的序列,序列里的数≤k,m个询问l,r:求sigma(i,1,k)c[i]^2,c[i]为i在[l,r]的出现次数。n,m,k≤50000。

题解:

莫队算法直接上。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define maxn 50010
 7 #define ll long long
 8 using namespace std;
 9 
10 inline int read(){
11     char ch=getchar(); int f=1,x=0;
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 f*x;
15 }
16 struct ask{int l,r,id;}asks[maxn]; int bel[maxn],n,sz,m,k,l,r; ll ans,a[maxn],c[maxn],p[maxn];
17 bool cmp(ask a,ask b){return bel[a.l]==bel[b.l]?a.r<b.r:bel[a.l]<bel[b.l];}
18 ll sqr(ll a){return a*a;}
19 int main(){
20     n=read(); m=read(); k=read(); inc(i,1,n)a[i]=read(); sz=(int)sqrt(n);
21     inc(i,1,n)bel[i]=(i-1)/sz+1; inc(i,1,m)asks[i]=(ask){read(),read(),i};
22     sort(asks+1,asks+m+1,cmp); ans=0; l=1; r=0;
23     inc(i,1,m){
24         while(asks[i].r>r)r++,ans-=sqr(c[a[r]]),c[a[r]]++,ans+=sqr(c[a[r]]);
25         while(asks[i].l<l)l--,ans-=sqr(c[a[l]]),c[a[l]]++,ans+=sqr(c[a[l]]);
26         while(asks[i].r<r)ans-=sqr(c[a[r]]),c[a[r]]--,ans+=sqr(c[a[r]]),r--;
27         while(asks[i].l>l)ans-=sqr(c[a[l]]),c[a[l]]--,ans+=sqr(c[a[l]]),l++;
28         p[asks[i].id]=ans;
29     }
30     inc(i,1,m)printf("%lld\n",p[i]); return 0;
31 }

 

20160906

posted @ 2016-09-11 15:42  YuanZiming  阅读(284)  评论(0编辑  收藏  举报