给一个序列和一些区间,每次询问对区间所有不同的数,求每个不同的出现的个数的平方*其值的总和
2*2*1+1*1*2
思路:
裸的莫队算法。
补:
1.cmp写错。
2.LL运算不会进行转化。
3.莫队的起始应该直接先处理好L,R。
卡了将近2.5h,水题让自己很生气。以及不会查错误真的撒比!
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> PII; const int N=1e6+10; LL num[N],res[N],c[N]; struct asd { int id,left,right; }e[200010]; int pos[200010]; int n,m; bool cmp(asd x,asd y) { if(pos[x.left]==pos[y.left]) return x.right<y.right; return pos[x.left]<pos[y.left]; } LL ans; void solve() { ans=0; sort(e,e+m,cmp); for(int i=e[0].left;i<=e[0].right;i++) { ans=ans+(2*num[c[i]]+1)*c[i]; num[c[i]]++; } res[e[0].id]=ans; int L=e[0].left,R=e[0].right; for(int i=1; i<m; i++) { while(R<e[i].right) { R++; ans=ans+((num[c[R]]<<1)+1)*c[R]; num[c[R]]++; } while(R>e[i].right) { num[c[R]]--; ans=ans-((num[c[R]]<<1)+1)*c[R]; R--; } while(L<e[i].left) { num[c[L]]--; ans=ans-((num[c[L]]<<1)+1)*c[L]; L++; } while(L>e[i].left) { L--; ans=ans+((num[c[L]]<<1)+1)*c[L]; num[c[L]]++; } res[e[i].id]=ans; } for(int i=0; i<m; i++) printf("%I64d ",res[i]); } int main() { scanf("%d%d",&n,&m); int block=(int)sqrt(n); for(int i=1;i<=n;i++) { scanf("%I64d",&c[i]); pos[i]=(i-1)/block+1; } for(int i=0;i<m;i++) { scanf("%d%d",&e[i].left,&e[i].right); e[i].id=i; } solve(); return 0; }