2018.12.30【国家集训队】【洛谷P1903】数颜色 / 维护队列(带修莫队)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/85372815

传送门


解析:

这道题好像以前在BZOJ上做过。

但是因为BZOJ数据较水,所以被我复杂度不对的代码搞过去了。。

真正的排序策略应该是这样的:

块大小设置成 n 2 3 n^{\frac{2}{3}}
左端点块不同就按照左端点块排序。
右端点块不同根据左端点块标号的奇偶性排序。
不然就按照时间戳的顺序排个序。

每次暴力修改时间戳,然后调整块的左右端点。

这样复杂度才是真正的 O ( n 5 3 ) O(n^{\frac{5}{3}})

证明自己用势能分析一下就行了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline int getint(){
    re int num;
    re char c;
    while(!isdigit(c=gc()));num=c^48;
    while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
    return num;
}

inline void outint(int a){
    static char ch[23];
    if(a==0)pc('0');
    while(a)ch[++ch[0]]=a-a/10*10,a/=10;
    while(ch[0])pc(ch[ch[0]--]^48);
}

inline char getalpha(){
    re char c;
    while(!isalpha(c=gc()));
    return c;
}

cs int N=100005,M=1000006;
int now,ans[N],l=1,r=0,cur;
int pre[N],pos[N],col[N],COL[N],cnt[M],tim[N];
int idxC,qcnt;

int B,block[N],bcnt;
struct Query{
    int l,r,tim,id,pre;
    friend bool operator<(cs Query &a,cs Query &b){
        if(block[a.l]^block[b.l])return block[a.l]<block[b.l];
        if(block[a.r]^block[b.r])return (block[a.l]&1)^(a.r>b.r);
        return a.pre<b.pre;
    }
}q[N];

inline void tim_r(int cur){
    if(l<=pos[cur]&&pos[cur]<=r){
        --cnt[COL[pos[cur]]];
        if(!cnt[COL[pos[cur]]])--now;
    }
    pre[cur]=COL[pos[cur]];
    COL[pos[cur]]=col[cur];
    if(l<=pos[cur]&&pos[cur]<=r){
        if(!cnt[COL[pos[cur]]])++now;
        ++cnt[COL[pos[cur]]];
    }
}

inline void tim_l(int cur){
    if(l<=pos[cur]&&pos[cur]<=r){
        --cnt[COL[pos[cur]]];
        if(!cnt[COL[pos[cur]]])--now;
    }
    COL[pos[cur]]=pre[cur];
    if(l<=pos[cur]&&pos[cur]<=r){
        if(!cnt[COL[pos[cur]]])++now;
        ++cnt[COL[pos[cur]]];
    }
}

inline void tim_adjust(int now){
    while(cur<idxC&&tim[cur+1]<=now)tim_r(++cur);
    while(cur&&tim[cur]>now)tim_l(cur--);
}

inline void add(int pos){
    if(!cnt[COL[pos]])++now;
    ++cnt[COL[pos]];
}

inline void del(int pos){
    --cnt[COL[pos]];
    if(!cnt[COL[pos]])--now;
}

int n,m;
signed main(){
    n=getint();
    m=getint();
    B=pow(n,2.0/3.0);
    bcnt=1;
    for(int re i=1;i<=n;++i){
        COL[i]=getint();
        block[i]=bcnt;
        if(i%B==0)++bcnt;
    }
    for(int re i=1;i<=m;++i){
        switch(getalpha()){
            case 'Q':{
                q[++qcnt].id=qcnt;
                q[qcnt].tim=i;
                q[qcnt].l=getint();
                q[qcnt].r=getint();
                q[qcnt].pre=idxC;
                break;
            }
            case 'R':{
                tim[++idxC]=i;
                pos[idxC]=getint();
                col[idxC]=getint();
                break;
            }
        }
    }    
    sort(q+1,q+qcnt+1);
    for(int re i=1;i<=qcnt;++i){
        tim_adjust(q[i].tim);
        while(r<q[i].r)add(++r);
        while(l>q[i].l)add(--l);
        while(r>q[i].r)del(r--);
        while(l<q[i].l)del(l++);
        ans[q[i].id]=now;
    }
    for(int re i=1;i<=qcnt;++i){
        outint(ans[i]);
        pc('\n');
    }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/85372815
今日推荐