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

思路

带修莫队的板子

带修莫队只需要多维护一个时间的指针即可,记录一下每个询问在第几次修改之后,再回退或者前进几个修改操作

排序的时候如果a.l和b.l在一个块里,就看r,如果a.r和b.r在一个块里,就看t

然后块的大小\(O(n^{\frac{2}{3} })\)最优,时间复杂度是\(O(n^{\frac{5}{3}})\)

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
struct Oper{
    int pos,from,to;
}M[50010];
struct Ask{
    int l,r,tim,id;
}Q[50010];
int L,R,T,barrel[1000100],ans,arr[50010],a[50010];
int n,m,siz,num,be[50010],out[50010];
bool cmp(Ask a,Ask b){
    return ((be[a.l]==be[b.l])?(be[a.r]==be[b.r]?a.tim<b.tim:be[a.r]<be[b.r]):be[a.l]<be[b.l]);
}
void going(int t,int opt){
    if(opt==1){
        arr[M[t].pos]=M[t].to;
        if(M[t].pos>=L&&M[t].pos<=R){
            barrel[M[t].from]--;
            if(!barrel[M[t].from])
                ans--;
            if(!barrel[M[t].to])
                ans++;
            barrel[M[t].to]++;
        }
    }
    else{
        arr[M[t].pos]=M[t].from;
        if(M[t].pos>=L&&M[t].pos<=R){
            barrel[M[t].to]--;
            if(!barrel[M[t].to])
                ans--;
            if(!barrel[M[t].from])
                ans++;
            barrel[M[t].from]++;
        }
    }
    T+=opt;
}
void movel(int opt){
    if(opt==1){
        barrel[arr[L]]--;
        if(!barrel[arr[L]])
            ans--;
    }
    else{
        if(!barrel[arr[L-1]])
            ans++;
        barrel[arr[L-1]]++;
    }
    L+=opt;
}
void mover(int opt){
    if(opt==1){
        if(!barrel[arr[R+1]])
            ans++;
        barrel[arr[R+1]]++;
    }
    else{
        barrel[arr[R]]--;
        if(!barrel[arr[R]])
            ans--;
    }
    R+=opt;
}
void calbe(void){
    siz=pow(n,0.6666666666);
    num=n/siz;
    if(n%siz)
        num++;
    for(int i=1;i<=n;i++)
        be[i]=i/siz+1;  
}
int main(){
    scanf("%d %d",&n,&m);
    int cnt=0,anscnt=0;;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),arr[i]=a[i];
    L=R=T=0;
    for(int i=1;i<=m;i++){
        char opt=getchar();
        while(opt!='R'&&opt!='Q')
            opt=getchar();
        if(opt=='R'){
            ++cnt;
            scanf("%d %d",&M[cnt].pos,&M[cnt].to);
            M[cnt].from=a[M[cnt].pos];
            a[M[cnt].pos]=M[cnt].to;
        }
        else{
            ++anscnt;
            Q[anscnt].id=anscnt;
            scanf("%d %d",&Q[anscnt].l,&Q[anscnt].r);
            Q[anscnt].tim=cnt;
        }
    }
    calbe();
    sort(Q+1,Q+anscnt+1,cmp);
    for(int i=1;i<=anscnt;i++){
        while(T<Q[i].tim)
            going(T+1,1);
        while(T>Q[i].tim)
            going(T,-1);
        while(L<Q[i].l)
            movel(1);
        while(L>Q[i].l)
            movel(-1);
        while(R<Q[i].r)
            mover(1);
        while(R>Q[i].r)
            mover(-1);
        out[Q[i].id]=ans;
    }
    for(int i=1;i<=anscnt;i++)
        printf("%d\n",out[i]);
    return 0;
}
posted @ 2019-04-08 11:16  dreagonm  阅读(203)  评论(0编辑  收藏  举报