原题位置: https://www.luogu.org/problem/show?pid=2709
这道题是莫队,据说在离线区间查询上,莫队无敌,但是感觉还好吧;
首先这道题是一个用来练手的好题,因为这是板子题;
所以主要就是排序,然后while查询;
至于排序方式 :
首先 ,应用分块思想,以查询左端点所在块为第一关键字, 以右端点为第二关键字 ,均从小到大排序;
然后就没有然后了;
———————–分割线啊——————————–
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define II int
#define R register
#define I 123456
using namespace std;
struct node {
II l,r,wei;
}aa[I];
II kuan, ans,n,m,k,l=1,r=0;
II c[I], kaa[I], a[I];
bool maP(node a1,node a2)
{
if(a1.l/kuan==a2.l/kuan) return a1.r<a2.r;
return a1.l/kuan<a2.l/kuan;
}
void add(R II x)
{
x=a[x];
ans-=c[x]*c[x];
c[x]++;
ans+=c[x]*c[x];
}
void dle(R II x)
{
x=a[x];
ans-=c[x]*c[x];
c[x]--;
ans+=c[x]*c[x];
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(R II i=1;i<=n;i++) scanf("%d",&a[i]);
for(R II i=1;i<=m;i++) scanf("%d%d",&aa[i].l,&aa[i].r), aa[i].wei=i;
kuan=sqrt(n);
sort(aa+1,aa+m+1,maP);
for(R II i=1;i<=n;i++)
{
while (r<aa[i].r) add(++r);// cout<<ans<<" ";
while (r>aa[i].r) dle(r--);// cout<<ans<<" ";
while (l<aa[i].l) dle(l++);// cout<<ans<<" ";
while (l>aa[i].l) add(--l);// cout<<ans<<" ";
// 每次更改时更新ans;
//cout<<endl;
kaa[aa[i].wei]=ans;
}
for(R II i=1;i<=m;i++) printf("%d\n",kaa[i]);
exit(0);
}
————————————-文末分割线————————————–
by pretend-fal
END;