题意:定义K[x]为元素x在区间[l,r]内出现的次数,那么它的贡献为K[x]*K[x]*x
给定一个序列,以及一些区间询问,求每个区间的贡献
算是莫队算法膜版题,不带修改的
Code
#include <cstdio> #include <algorithm> #include <cmath> #define N 200010 #define ll long long using namespace std; int n,m,A[N],bl[N],k[N*5]; ll sum,Ans[N]; struct info{ int l,r,id; friend bool operator <(info a,info b){ return (bl[a.l]==bl[b.l])?a.r<b.r:a.l<b.l; } }q[N]; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void upd(int x,int d){ sum-=k[A[x]]*1ll*k[A[x]]*A[x]; k[A[x]]+=d; sum+=k[A[x]]*1ll*k[A[x]]*A[x]; } int main(){ n=read(),m=read();int blo=sqrt(n); for(int i=1;i<=n;++i) A[i]=read(),bl[i]=i/blo+1; for(int i=1;i<=m;++i) q[i].l=read(),q[i].r=read(),q[i].id=i; sort(q+1,q+m+1); for(int i=1,l=1,r=0;i<=m;++i){ for(;l<q[i].l;++l) upd(l,-1); for(;l>q[i].l;--l) upd(l-1,1); for(;r<q[i].r;++r) upd(r+1,1); for(;r>q[i].r;--r) upd(r,-1); Ans[q[i].id]=sum; } for(int i=1;i<=m;printf("%lld ",Ans[i++])); return 0; }