【模板】莫队
传送门
题目描述
小B 有一个长为 n 的整数序列 a,值域为 [1,k]。
他一共有 mm 个询问,每个询问给定一个区间 [l,r],求:

其中 ci 表示数字 i 在 [l,r] 中的出现次数。
小B请你帮助他回答询问。
输入格式
第一行三个整数 n,m,k。
第二行 n 个整数,表示 小B 的序列。
接下来的 m 行,每行两个整数 l,r。
输出格式
输出 m 行,每行一个整数,对应一个询问的答案。
说明/提示
【数据范围】
对于 100% 的数据,1≤n,m,k≤5×10^4。
莫队模板↓
#include<iostream> #include<sstream> #include<cstring> #include<cmath> #include<cstdio> #include<queue> #include<algorithm> using namespace std; int ans=0,cs[500001],a[500001],Ans[500001],n,Q,k,Size; struct node{ int l,r,num; }q[500001]; int cmp(node XXX,node YYY){ if(XXX.l/Size==YYY.l/Size) return XXX.r<YYY.r; return XXX.l/Size<YYY.l/Size; } int del(int X){ ans-=(2*cs[a[X]]-1);//(X-1)^2=X^2-2*X+1; cs[a[X]]--; return 0; } int add(int X){ ans+=(2*cs[a[X]]+1);//(X+1)^2=X^2+2*X+1; cs[a[X]]++; return 0; } int main(){ scanf("%d%d%d",&n,&Q,&k); Size=(int)sqrt(n);//离散分块 for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=Q;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].num=i; } sort(q+1,q+Q+1,cmp); int l=1,r=0; for(int i=1;i<=Q;i++){ int L=q[i].l,R=q[i].r; while(l<L) del(l++); while(l>L) add(--l); while(r<R) add(++r); while(r>R) del(r--); Ans[q[i].num]=ans; } for(int i=1;i<=Q;i++) printf("%d\n",Ans[i]); return 0; }

浙公网安备 33010602011771号