莫队裸题。
维护的时候有的打法是利用(a-1)^2==a^2-2*a+1转移,也可以,但是通用性不太够。
下面的打法就是先把这个点的贡献删掉,然后更新这个点,再把这个点的贡献加回来,这种解法更加通用一些。
剩下的是我分块的时候i/part打成n/part了,TLE30,改了就A了,还是要注意对拍呀。

#include<bits/stdc++.h> using namespace std; struct MoCap{ int l,r,id; }q[50005]; int n,m,k,ans[50005],part,ans1,sum[50005],col[50005],bl[50005]; int read(){ int sum=0,f=1;char x=getchar(); while(x<'0'||x>'9'){ if(x=='-') f=-1; x=getchar(); }while(x>='0'&&x<='9'){ sum=sum*10+x-'0'; x=getchar(); }return sum*f; } bool cmp(MoCap a,MoCap b){ return (bl[a.l]^bl[b.l])?bl[a.l]<bl[b.l]:((bl[a.l]&1)?a.r<b.r:a.r>b.r); } void updata(int i,int val){ ans1-=sum[col[i]]*sum[col[i]]; sum[col[i]]+=val; ans1+=sum[col[i]]*sum[col[i]]; } int main(){ n=read();m=read();k=read();part=sqrt(n); for(int i=1;i<=n;i++){ col[i]=read(); bl[i]=i/part+1; } for(int i=1;i<=m;i++){ q[i].l=read();q[i].r=read(); q[i].id=i; }sort(q+1,q+1+m,cmp); int l=1,r=0; // cout<<endl; for(int i=1;i<=m;i++){ while(l<q[i].l) updata(l++,-1); while(l>q[i].l) updata(--l,1); while(r<q[i].r) updata(++r,1); while(r>q[i].r) updata(r--,-1); // cout<<q[i].id<<" "<<ans1<<endl; // for(int j=1;j<=n;j++) // cout<<sum[col[j]]<<" ";cout<<endl; ans[q[i].id]=ans1; } for(int i=1;i<=m;i++) printf("%d ",ans[i]); return 0; }