题意:给你一列数,对于区间LR,中的每一个数,我们都计算他出现了X次,然后价值就是x*x*这个数,然后加和就行了
思路:很久没有写过莫队,有一点点忘了,莫队的公式就是把(x+1)^2展开就可以得到,注意爆int
代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=2e5+7; int block,a[maxn],cnt[1000007]; LL res[maxn]; LL ans; struct node { int l,r,id; }q[maxn]; bool cmp(node a,node b) { return a.l/block!=b.l/block?a.l/block<b.l/block:a.r<b.r; } void update(int p,int val) { if(val==1){ ans+=cnt[a[p]]*2*a[p]+a[p]; cnt[a[p]]++; } else{ ans-=cnt[a[p]]*2*a[p]; ans+=a[p]; cnt[a[p]]--; } } int main() { int n,t; while(~scanf("%d%d",&n,&t)){ memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } block=sqrt(n); for(int i=1;i<=t;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q+1,q+1+t,cmp); ans=0; for(int i=1,l=1,r=0;i<=t;i++){ for(;r<q[i].r;r++) update(r+1,1); for(;r>q[i].r;r--) update(r,-1); for(;l<q[i].l;l++) update(l,-1); for(;l>q[i].l;l--) update(l-1,1); res[q[i].id]=ans; } for(int i=1;i<=t;i++){ printf("%lld ",res[i]); } } return 0; }