树套树模版

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<stack>
#include<vector>
#define Tp Treap*
#define DTp pair<Tp,Tp>
#define ft first
#define sc second
#define MAXN 50000+10
#define INF 2147483647
using namespace std;
struct SBT{
    struct Treap{
        Tp l;Tp r;
        int key,size,fix;
    };
    Tp root;
    int Size(Tp A){
        return (A?A->size:0);
    }
    void upd(Tp A){
        A->size=Size(A->l)+Size(A->r)+1;
    }
    void Print(Tp A,int k){
        if(!A)return;
        Print(A->l,k+1);
        printf("%d,",A->key);
        Print(A->r,k+1);
        if(!k)printf("\n");
    }
    Tp new_treap(int v){
        Tp ret;ret=new Treap();
        ret->l=ret->r=NULL;
        ret->key=v,ret->size=1,ret->fix=rand();
        return ret;
    }
    Tp Build(int a[],int L,int R){
        vector<int> b;
        stack<Tp> s;
        Tp lst;
        for(int i=L;i<=R;i++)b.push_back(a[i]);
        sort(b.begin(),b.end());
        for(int i=0;i<b.size();i++){
            Tp x=new_treap(b[i]);
            lst=NULL;
            while(!s.empty()&&s.top()->fix>x->fix){
                upd(s.top());
                lst=s.top();
                s.pop();
            }
            if(!s.empty()) s.top()->r=x;
            x->l=lst;
            s.push(x);
        }
        while(!s.empty()){
            upd(s.top());
            lst=s.top();
            s.pop();
        }
        return lst;
    }
    Tp Merge(Tp A,Tp B){
        if(!A)return B;
        if(!B)return A;
        if(A->fix<B->fix){
            A->r=Merge(A->r,B);
            upd(A);
            return A;
        }
        else{
            B->l=Merge(A,B->l);
            upd(B);
            return B;
        }
    }
    DTp Split(Tp A,int k){
        if(!A)return DTp(NULL,NULL);
        DTp y;
        if(Size(A->l)>=k){
            y=Split(A->l,k);
            A->l=y.sc;
            upd(A);
            y.sc=A;
        }
        else{
            y=Split(A->r,k-Size(A->l)-1);
            A->r=y.ft;
            upd(A);
            y.ft=A;
        }
        return y;
    }
    int GetKth(Tp A,int v){
        if(!A)return 0;
        return (v<=A->key?GetKth(A->l,v):GetKth(A->r,v)+Size(A->l)+1);
    }
    int Pre(int v){
        int k=GetKth(root,v);
        if(!k)return -INF; //!!!
        DTp x=Split(root,k-1);
        DTp y=Split(x.sc,1);
        int ans=(y.ft?y.ft->key:-INF);
        root=Merge(x.ft,Merge(y.ft,y.sc));
        return ans;
    }
    int Nxt(int v){
        int k=GetKth(root,v+1);
        DTp x=Split(root,k);
        DTp y=Split(x.sc,1);
        int ans=(y.ft?y.ft->key:INF);
        root=Merge(x.ft,Merge(y.ft,y.sc));
        return ans;
    }
    void Delete(int v){
        int k=GetKth(root,v);
        DTp x=Split(root,k);
        DTp y=Split(x.sc,1);
        root=Merge(x.ft,y.sc);
    }
    void Insert(int v){
        int k=GetKth(root,v);
        DTp x=Split(root,k);
        Tp t=new_treap(v);
        root=Merge(x.ft,Merge(t,x.sc));
    }
}dat[MAXN<<2];
int a[MAXN];
int n,m;
void build(int k,int L,int R){
    dat[k].root=dat[k].Build(a,L,R-1);
    if(L+1==R)return;
    build(k<<1,L,(L+R)>>1);
    build(k<<1|1,(L+R)>>1,R);
}
int rk(int a,int b,int k,int L,int R,int x){// ret=ans-1
    int mid=(L+R)>>1;
    if(a<=L&&R<=b)return dat[k].GetKth(dat[k].root,x);
    if(b<=mid)return rk(a,b,k<<1,L,mid,x);
    if(a>=mid)return rk(a,b,k<<1|1,mid,R,x);
    return rk(a,b,k<<1,L,mid,x)+rk(a,b,k<<1|1,mid,R,x);
}
int getx(int a,int b,int k){
    int L=0,R=100000000;
    while(R-L>1){
        int mid=(L+R)>>1;
        int k1=rk(a,b+1,1,1,n+1,mid)+1;
        int k2=rk(a,b+1,1,1,n+1,mid+1);
        if(k1<=k&&k<=k2)return mid;
        if(k2<k){
            L=mid;
        }
        else if(k1>k){
            R=mid;
        }
    }
    int k1=rk(a,b+1,1,1,n+1,L);k1++;
    int k2=rk(a,b+1,1,1,n+1,L+1);
    if(k1<=k&&k<=k2)return L;
    else return R;
}
int pre(int a,int b,int k,int L,int R,int x){
    int mid=(L+R)>>1;
    if(a<=L&&R<=b)return dat[k].Pre(x);
    if(b<=mid)return pre(a,b,k<<1,L,mid,x);
    if(a>=mid)return pre(a,b,k<<1|1,mid,R,x);
    return max(pre(a,b,k<<1,L,mid,x),pre(a,b,k<<1|1,mid,R,x));
}
int nxt(int a,int b,int k,int L,int R,int x){
    int mid=(L+R)>>1;
    if(a<=L&&R<=b)return dat[k].Nxt(x);
    if(b<=mid)return nxt(a,b,k<<1,L,mid,x);
    if(a>=mid)return nxt(a,b,k<<1|1,mid,R,x);
    return min(nxt(a,b,k<<1,L,mid,x),nxt(a,b,k<<1|1,mid,R,x));
}
void update(int a,int k,int L,int R,int x,int y){
    dat[k].Delete(x);
    dat[k].Insert(y);
    if(L+1==R)return;
    int mid=(L+R)>>1;
    if(a<mid)update(a,k<<1,L,mid,x,y);
    else update(a,k<<1|1,mid,R,x,y);
}
void init(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    build(1,1,n+1);
}
void AskRk(){
    int L,R,x;
    scanf("%d%d%d",&L,&R,&x);
    printf("%d\n",rk(L,R+1,1,1,n+1,x)+1);
}
void AskNum(){
    int L,R,k;
    scanf("%d%d%d",&L,&R,&k);
    printf("%d\n",getx(L,R,k));
}
void AskUpd(){
    int pos,x;
    scanf("%d%d",&pos,&x);
    update(pos,1,1,n+1,a[pos],x);
    a[pos]=x;
}
void AskPre(){
    int L,R,x;
    scanf("%d%d%d",&L,&R,&x);
    int ans=pre(L,R+1,1,1,n+1,x);
    printf("%d\n",(ans<x?ans:-INF));
}
void AskNxt(){
    int L,R,x;
    scanf("%d%d%d",&L,&R,&x);
    int ans=nxt(L,R+1,1,1,n+1,x);
    printf("%d\n",(ans>x?ans:INF));
}
void solve(){
    int opt;
    while(m--){
        scanf("%d",&opt);
        switch(opt){
            case 1:AskRk();break;
            case 2:AskNum();break;
            case 3:AskUpd();break;
            case 4:AskPre();break;
            case 5:AskNxt();
        }
    }
}
int main()
{
//    freopen("data.in","r",stdin);
//    freopen("my.out","w",stdout);
    init();
    solve();
    return 0;
}

 

posted @ 2017-12-27 23:28  white_hat_hacker  阅读(137)  评论(0编辑  收藏  举报