洛谷P3285/LOJ2212/BZOJ3595[SCOI2014]方伯伯的OJ(线段树)

不会维护区间的Splay QAQ。题目n这么大,直接维护是肯定不行的,考虑维护区间内删去的点,那么减一下就是区间内原有的点,可以解决第k大和排名,至于按编号检索,用两个map维护编号和线段树位置之间的关系,修改时维护一下即可。

#include<cstdio>
#include<map>
using namespace std;
const int N=100050;
char rB[1<<21],*rS,*rT,wB[1<<21];
int wp=-1;
inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,1<<21,stdin),rS==rT)?EOF:*rS++;}
inline void flush(){fwrite(wB,1,wp+1,stdout);wp=-1;}
inline void pc(char c){if(wp+1==(1<<21))flush();wB[++wp]=c;}
inline int rd(){
    char c=gc();
    while(c<48||c>57)c=gc();
    int x=c&15;
    for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15);
    return x;
}
short buf[15];
inline void wt(int x){
    short l=-1;
    while(x>9){
        buf[++l]=x%10;
        x/=10;
    }
    pc(x|48);
    while(l>=0)pc(buf[l--]|48);
    pc('\n');
}
int cnt[N<<5],lc[N<<5],rc[N<<5],sz=1,rt=1,lft,rgt;
map<int,int> pos,id;
inline int Max(int a,int b){return a>b?a:b;}
inline int Min(int a,int b){return a<b?a:b;}
inline int pid(int x){return id.find(x)==id.end()?x:id[x];}
inline int idp(int x){return pos.find(x)==pos.end()?x:pos[x];}
void add(int &o,int L,int R,int x){
    if(!o)o=++sz;
    ++cnt[o];
    if(L<R){
        int M=L+R>>1;
        if(x<=M)add(lc[o],L,M,x);
        else add(rc[o],M+1,R,x);
    }
}
int kth(int o,int L,int R,int k){
    if(L==R)return pid(L);
    int M=L+R>>1,s=Max(0,Min(M,rgt)-Max(L,lft)+1-cnt[lc[o]]);
    return k<=s?kth(lc[o],L,M,k):kth(rc[o],M+1,R,k-s);
}
int rnk(int o,int L,int R,int x){
    if(!cnt[o]||L==R)return 0;
    int M=L+R>>1;
    if(x<=M)return rnk(lc[o],L,M,x);
    return cnt[lc[o]]+rnk(rc[o],M+1,R,x);
}
int main(){
    int n=rd(),m=rd(),t,x,y,p,lans=0,tL=1-m,tR=n+m,res;
    lft=1;rgt=n;
    while(m--){
        t=rd();x=rd()-lans;
        if(t==4)wt(lans=kth(rt,tL,tR,x));
        else{
            p=idp(x);
            wt(res=p-lft+1-rnk(rt,tL,tR,p));
            if(t==2){
                pos[x]=--lft;id[lft]=x;
                add(rt,tL,tR,p);
            }else if(t==3){
                pos[x]=++rgt;id[rgt]=x;
                add(rt,tL,tR,p);
            }else{pos[id[p]=y=rd()-lans]=p;}
            lans=res;
        }
    }
    flush();
    return 0;
}
View Code

 

posted @ 2019-07-31 14:11  wangyuchen  阅读(170)  评论(0编辑  收藏  举报