Luogu1903/Bzoj2120 数颜色 / 维护队列(待修莫队模板)

块大小n ^2/3 ,时间复杂度 n^5/3

左端点-右端点-时间

#include<bits/stdc++.h>
using namespace std; 
const int maxn=10004;
int n,m,tot=0,tot1=0,bel[maxn],blo,vis[1000004],col[maxn],S[maxn],ans[maxn],num=0;
//vis记录颜色出现多少次,num记录不同颜色个数 
int l=0,r=0,o=0;
struct node{
    int id,last,l,r;
}a[maxn],b[maxn];
bool operator < (const node &x,const node &y){
    if(bel[x.l]==bel[y.l]){
        if(bel[x.r]==bel[y.r]) return x.last<y.last;
        return bel[x.r]<bel[y.r];
    }
    return bel[x.l]<bel[y.l];
}
inline void change1(int x){//时间后移 b[x].l from col[b[x].l] to b[x].r
    if(col[b[x].l]!=b[x].r){
        if(b[x].l<=r&&b[x].l>=l){
            vis[b[x].r]++;
            if(vis[b[x].r]==1) num++;
            vis[col[b[x].l]]--;
            if(!vis[col[b[x].l]]) num--;
        }
        col[b[x].l]=b[x].r;
    }
}
inline void change(int x){//时间倒流 b[x].l from col[b[x].l] to b[x].last
    if(col[b[x].l]!=b[x].last){
        if(b[x].l<=r&&b[x].l>=l){
            vis[b[x].last]++;
            if(vis[b[x].last]==1) num++;
            vis[col[b[x].l]]--;
            if(!vis[col[b[x].l]]) num--;
        }
        col[b[x].l]=b[x].last;
    }
}
inline void add(int x){
    vis[col[x]]++;
    if(vis[col[x]]==1) num++;
}
inline void del(int x){
    vis[col[x]]--;
    if(!vis[col[x]]) num--;
}
int main(){
    scanf("%d%d",&n,&m);
    blo=pow(n,2.0/3);
    for(int i=1;i<=n;i++){
        bel[i]=(i-1)/blo+1;
        scanf("%d",&col[i]);
        S[i]=col[i];
    }
    for(int i=1;i<=m;i++){ 
        char s[5];
        scanf("%s",s);
        if(s[0]=='Q'){
            tot++;
            scanf("%d%d",&a[tot].l,&a[tot].r);
            a[tot].id=tot;
            a[tot].last=tot1;
        }else{
            tot1++;//l位置,r元素值 
            scanf("%d%d",&b[tot1].l,&b[tot1].r);
            b[tot1].last=S[b[tot1].l];//为了删除 ,记录上一个修改的颜色信息 
            S[b[tot1].l]=b[tot1].r;
        }
    }
    sort(a+1,a+tot+1);
    for(int i=1;i<=tot;i++){
        while(o<a[i].last) change1(++o);//时间后移 
        while(o>a[i].last) change(o--);//时间倒流 
        while(r<a[i].r) add(++r);
        while(l>a[i].l) add(--l);
        while(l<a[i].l) del(l++);
        while(r>a[i].r) del(r--);
        ans[a[i].id]=num;
    }
    for(int i=1;i<=tot;i++){
        printf("%d\n",ans[i]);
    }
}

猜你喜欢

转载自www.cnblogs.com/wifimonster/p/10328739.html
今日推荐