莫队

莫队模板题

相当于优化的暴力,每一次调整左右节点的位置

#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";
}
posted @ 2025-11-22 16:54  wtnbl  阅读(0)  评论(0)    收藏  举报