[BZOJ2120]数颜色:带修莫队/树套树

分析:

填个以前的坑。

代码:

带修莫队:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
const int MAXN=50005;
const int MAXD=1005;
int n,m,qcnt,dcnt,K,a[MAXN],now[MAXN],s[1000005],ans[MAXN];
struct Quest{
    int l,r,lk,rk,t,no;
}q[MAXN];
struct Modify{
    int loc,col,ver;
}d[MAXN];
bool cmp(Quest x,Quest y){
    if(x.lk<y.lk) return 1;
    if(x.lk>y.lk) return 0;
    if(x.r<y.r) return 1;
    if(x.r>y.r) return 0;
    return x.t<y.t;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) now[i]=a[i]=read();
    K=pow(n,(double)0.66);
    for(int i=1;i<=m;i++){
        char opt[12];
        scanf("%s",opt+1);
        if(opt[1]=='Q'){
            qcnt++;
            q[qcnt].l=read();
            q[qcnt].lk=(q[qcnt].l-1)/K+1;
            q[qcnt].r=read();
            q[qcnt].rk=(q[qcnt].r-1)/K+1;
            q[qcnt].t=dcnt;
            q[qcnt].no=qcnt;
        }
        else{
            dcnt++;
            d[dcnt].loc=read();
            d[dcnt].col=read();
            d[dcnt].ver=now[d[dcnt].loc];
            now[d[dcnt].loc]=d[dcnt].col;
        }
    }
    int h=1,t=0,tim=0,sum=0;
    for(int i=1;i<=qcnt;i++){
        for(int j=tim+1;j<=q[i].t;j++){
            int pre=a[d[j].loc];
            a[d[j].loc]=d[j].col;
            if(d[j].loc<h||d[j].loc>t) continue;
            s[pre]--;s[d[j].col]++;
            if(s[pre]==0) sum--;
            if(s[d[j].col]==1) sum++;
        }
        for(int j=tim;j>q[i].t;j--){
            int pre=a[d[j].loc];
            a[d[j].loc]=d[j].ver;
            if(d[j].loc<h||d[j].loc>t) continue;
            s[pre]--;s[d[j].ver]++;
            if(s[pre]==0) sum--;
            if(s[d[j].ver]==1) sum++;
        }
        for(;t<q[i].r;){
            t++;
            s[a[t]]++;
            if(s[a[t]]==1) sum++;
        }
        for(;t>q[i].r;t--){
            s[a[t]]--;
            if(s[a[t]]==0) sum--;
        }
        for(;h<q[i].l;h++){
            s[a[h]]--;
            if(s[a[h]]==0) sum--;
        }
        for(;h>q[i].l;){
            h--;
            s[a[h]]++;
            if(s[a[h]]==1) sum++;
        }
        ans[q[i].no]=sum;
        tim=q[i].t;
    }
    for(int i=1;i<=qcnt;i++) printf("%d\n",ans[i]);
    return 0;
}

树套树:

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9665277.html