莫队
相当于优化的暴力,每一次调整左右节点的位置
#include <bits/stdc++.h>
using namespace std;
int n,m,k;
const int N=5e4+5;
int a[N];
int cnt[N];//用于计算当前区间i出现了几次
int ans[N];
int blocksize;
struct Node
{
int l,r,id;
bool operator<(const Node &no)
{
if(l/blocksize!=no.l/blocksize)
return l/blocksize<no.l/blocksize;
return (l/blocksize%2==0)?r<no.r:r>no.r;//注意这里是根据块的奇偶性进行优化
}
};
vector<Node> q;
int ns=0;
void add(int &x)
{
ns+=cnt[x]*2+1;
cnt[x]+=1;
}
void remove(int &x)
{
ns+=-2*cnt[x]+1;
cnt[x]-=1;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n>>m>>k;
blocksize=ceil(pow(n,0.5));//直接用sqrt也可以
for(int i=1;i<=n;i++)
cin>>a[i];
q.emplace_back();
for(int i=1;i<=m;i++)
{
int l,r;
cin>>l>>r;
q.push_back({l,r,i});
}
sort(q.begin()+1,q.end());
int pl=1,pr=0;//定义空的区间
for(int i=1;i<=m;i++)
{
auto &nq=q[i];
while(pl>nq.l)
add(a[--pl]);
while(pr<nq.r)
add(a[++pr]);
while(pr>nq.r)
remove(a[pr--]);
while(pl<nq.l)
remove(a[pl++]);
//注意这一段的while顺序不能变
ans[nq.id]=ns;
}
for(int i=1;i<=m;i++)
cout<<ans[i]<<"\n";
}

浙公网安备 33010602011771号