https://www.luogu.org/problemnew/show/P2709
无修改的莫队几乎没有什么太高深的套路,比较模板吧,大多都是在那两个函数上动手脚。
这题询问每一种数字数量的平方和,那么我们在左移或右移的时候记录一下就好了,当每一种数字的种类数加1或减1的时候,我们需要减去以前这个数对答案的影响,加上现在对答案的影响。
假设原来数字a的种类数为k,如今又加入一个a,那么先ans-=k^2,然后ans+=(k+1)^2.,删除同理。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define N int(5e5+2)
#define M int(2e5+2)
using namespace std;
struct ahah{
int L,R,p,f;
}ask[N];
int answer,n,m,q,a[N],cnt[N],ans[N],k;
bool cmp(ahah a,ahah b){ return a.p<b.p; }
bool comp(ahah a,ahah b){ return a.L/k==b.L/k?a.R<b.R:a.L<b.L; }
void remove(int pos)
{
answer-=cnt[a[pos]]*cnt[a[pos]],--cnt[a[pos]],answer+=cnt[a[pos]]*cnt[a[pos]];
}
void add(int pos)
{
answer-=cnt[a[pos]]*cnt[a[pos]],++cnt[a[pos]],answer+=cnt[a[pos]]*cnt[a[pos]];
}
int main()
{
scanf("%d%d%d",&n,&q,&m);
k=sqrt(n);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=;i<=q;i++)scanf("%d%d",&ask[i].L,&ask[i].R),ask[i].p=i;
sort(ask+,ask++q,comp);
int curl=,curr=;
for(int i=;i<=q;i++)
{
int L=ask[i].L,R=ask[i].R;
while(curl<L)remove(curl++);
while(curl>L)add(--curl);
while(curr<R)add(++curr);
while(curr>R)remove(curr--);
ans[ask[i].p]=answer;
}
for(int i=;i<=q;i++)printf("%d\n",ans[i]-); //here很神,发现不改比样例都大1
}