[国家集训队]数颜色|维护队列

P1903 [国家集训队]数颜色 / 维护队列

带修莫队模板题

增加了一维时间轴,表示当前的状态,就是然后就是三维莫队的写法了,对l进行分块之后,对r进行分块,然后再对t进行排序即可。

// Created by CAD
#include <bits/stdc++.h>

using namespace std;

const int maxn=1e6+5;
int belo[maxn],a[maxn];
struct query{
    int l,r,t,id;
    bool operator <(const query &q)const {
        return belo[l]!=belo[q.l]?belo[l]<belo[q.l]:(belo[r]!=belo[q.r]?belo[r]<belo[q.r]:(belo[r]&1)?t<q.t:t>q.t);
    }
}q[maxn];
struct modify{
    int pos,val;
}u[maxn];
int ans[maxn],now,num[maxn];
inline void add(int &x){
    now+=num[x]++==0;
}
inline void del(int &x){
    now-=--num[x]==0;
}

int main() {
    int n,m;scanf("%d%d",&n,&m);
    int blo=pow(n,2/3.0);
    for(int i=1;i<=n;++i){
        scanf("%d",a+i);
        belo[i]=(i-1)/blo+1;
    }
    int time=0,cnt=0;
    for(int i=1;i<=m;++i){
        char op;
        int l,r;
        scanf("%s%d%d",&op,&l,&r);
        if(op=='Q')
            q[++cnt]={l,r,time,cnt};
        else
            u[++time]={l,r};
    }
    sort(q+1,q+cnt+1);
    int l=1,r=0;
    time=0;
    for(int i=1;i<=cnt;++i){
        int ql=q[i].l,qr=q[i].r,qt=q[i].t;
        while(l<ql) del(a[l++]);
        while(l>ql) add(a[--l]);
        while(r<qr) add(a[++r]);
        while(r>qr) del(a[r--]);

        while(time!=qt){
            if(time<qt) ++time;

            int &pos=u[time].pos,&val=u[time].val;
            if(pos>=ql&&pos<=qr)
                del(a[pos]),add(val);
            swap(a[pos],val);

            if(time>qt) --time;
        }
        ans[q[i].id]=now;
    }

    for(int i=1;i<=cnt;++i)
        printf("%d\n",ans[i]);
    return 0;
}
posted @ 2021-04-29 14:55  caoanda  阅读(85)  评论(0编辑  收藏  举报