这个题可以用莫队的方法来解决,通过创建数组来保存数的出现个数,再在每次添加或删除的时候保存一个答案,这样就能做出这道题。
#include<stdio.h> #include<math.h> struct node{ int l,r,id; }a[100001],pxr[100001]; int n,sqn,m,js[100001],b[100001],ans,cnt[100001],nowl,nowr; int kx; int cmp(struct node a1,struct node a2){return(a1.l/sqn)==(a2.l/sqn)?a1.r<a2.r:a1.l<a2.l;} int px(int l,int r){ if(l==r)return 0; int k,s,mid,p; mid=(l+r)>>1; k=l;s=mid+1;p=l; px(l,mid);px(mid+1,r); while(k<=mid&&s<=r)if(cmp(a[k],a[s]))pxr[p++]=a[k++];else pxr[p++]=a[s++]; while(k<=mid)pxr[p++]=a[k++]; while(s<=r)pxr[p++]=a[s++]; for(p=l;p<=r;p++)a[p]=pxr[p]; return 0; } void add(int x){ ans=ans-js[b[x]]*js[b[x]]+(js[b[x]]+1)*(js[b[x]]+1); ++js[b[x]]; } void del(int x){ ans=ans-js[b[x]]*js[b[x]]+(js[b[x]]-1)*(js[b[x]]-1); --js[b[x]]; } int read(){ int res=0,zf=1; char ch; while((ch=getchar())<48||ch>57)if(ch=='-')zf=!zf; res=(ch^48); while((ch=getchar())>=48&&ch<=57)res=(res<<3)+(res<<1)+(ch^48); return zf?res:(-res); } int main(){ n=read(); m=read(); kx=read(); sqn=sqrt(n); for(int i=1;i<=n;i++)b[i]=read(); for(int i=1;i<=m;i++){a[i].l=read();a[i].r=read();a[i].id=i;} px(1,m); ans=-1; for(int i=1;i<=m;i++){ while(nowr<a[i].r)add(++nowr); while(nowr>a[i].r)del(nowr--); while(nowl<a[i].l)del(nowl++); while(nowl>a[i].l)add(--nowl); cnt[a[i].id]=ans; } for(int i=1;i<=m;i++)printf("%d ",cnt[i]); return 0; }