bzoj3196

线段树套treap

#include<cstdio>
#include<cctype>
#include<algorithm>
#define maxn 200001
#define maxm 3000002
using namespace std;
int n,m,size,res,a[maxn],root[maxn];
int ls[maxm],rs[maxm],rnd[maxm],w[maxm],siz[maxm],v[maxm];
inline void read(int &x){
    char ch=getchar();x=0;int f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    x*=f;
}
inline void updata(int x){siz[x]=siz[ls[x]]+siz[rs[x]]+w[x];}
inline void rturn(int &x){int tmp=ls[x];ls[x]=rs[tmp];rs[tmp]=x;siz[tmp]=siz[x];updata(x);x=tmp;}
inline void lturn(int &x){int tmp=rs[x];rs[x]=ls[tmp];ls[tmp]=x;siz[tmp]=siz[x];updata(x);x=tmp;}
inline void insert(int &k,int num){
    if(!k){k=++size;siz[k]=w[k]=1;v[k]=num;rnd[k]=rand();return;}
    siz[k]++;
    if(num==v[k])w[k]++;
    else if(num<v[k]){insert(ls[k],num);if(rnd[ls[k]]<rnd[k])rturn(k);}
    else{insert(rs[k],num);if(rnd[rs[k]]<rnd[k])lturn(k);}
}
inline void buildtr(int k,int l,int r,int x,int num){
    insert(root[k],num);
    if(l==r)return;
    int mid=(l+r)>>1;
    if(x<=mid)buildtr(k<<1,l,mid,x,num);else buildtr(k<<1|1,mid+1,r,x,num);
}
inline void del(int &k,int num){
    if(v[k]==num){
        if(w[k]>1){w[k]--;siz[k]--;return;}
        if(ls[k]*rs[k]==0)k=ls[k]+rs[k];
        else if(rnd[ls[k]]<rnd[rs[k]]){rturn(k);del(k,num);}
        else {lturn(k);del(k,num);}
    }
    else if(num<v[k]){del(ls[k],num);siz[k]--;}
    else{del(rs[k],num);siz[k]--;}
}
inline void ask_rank(int k,int num){
    if(!k)return;
    if(num==v[k]){res+=siz[ls[k]];return;}
    else if(num<v[k])ask_rank(ls[k],num);
    else{res+=siz[ls[k]]+w[k];ask_rank(rs[k],num);}
}
inline void get_rank(int k,int l,int r,int x,int y,int num){
    if(l==x && r==y){ask_rank(root[k],num);return;}
    int mid=(l+r)>>1;
    if(mid>=y)get_rank(k<<1,l,mid,x,y,num);
    else if(mid<x)get_rank(k<<1|1,mid+1,r,x,y,num);
    else{
        get_rank(k<<1,l,mid,x,mid,num);
        get_rank(k<<1|1,mid+1,r,mid+1,y,num);
    }
}
inline void get_index(int x,int y,int z){
    int l=0,r=1e9,ans;
    while(l<=r){
        int mid=(l+r)>>1;
        res=1;get_rank(1,1,n,x,y,mid);
        if(res<=z){l=mid+1;ans=mid;}else r=mid-1;
    }
    printf("%d\n",ans);
}
inline void change(int k,int l,int r,int x,int num,int y){
    del(root[k],y);
    insert(root[k],num);
    if(l==r)return;
    int mid=(l+r)>>1;
    if(x<=mid)change(k<<1,l,mid,x,num,y);else change(k<<1|1,mid+1,r,x,num,y);
}
inline void get_pre(int k,int num){
    if(!k)return;
    if(v[k]<num){res=max(v[k],res);get_pre(rs[k],num);}else get_pre(ls[k],num);
}
inline void get_suc(int k,int num){
    if(!k)return;
    if(v[k]>num){res=min(res,v[k]);get_suc(ls[k],num);}else get_suc(rs[k],num);
}
inline void ask_after(int k,int l,int r,int x,int y,int num){
    if(l==x && r==y){get_suc(root[k],num);return;}
    int mid=(l+r)>>1;
    if(mid>=y)ask_after(k<<1,l,mid,x,y,num);
    else if(mid<x)ask_after(k<<1|1,mid+1,r,x,y,num);
    else{
        ask_after(k<<1,l,mid,x,mid,num);
        ask_after(k<<1|1,mid+1,r,mid+1,y,num);
    }
}
inline void ask_before(int k,int l,int r,int x,int y,int num){
    if(l==x && r==y){get_pre(root[k],num);return;}
    int mid=(l+r)>>1;
    if(mid>=y)ask_before(k<<1,l,mid,x,y,num);
    else if(mid<x)ask_before(k<<1|1,mid+1,r,x,y,num);
    else{
        ask_before(k<<1,l,mid,x,mid,num);
        ask_before(k<<1|1,mid+1,r,mid+1,y,num);
    }
}
int main(){
    int typ,x,y,z;
    read(n);read(m);
    for(int i=1;i<=n;i++)read(a[i]);
    for(int i=1;i<=n;i++)buildtr(1,1,n,i,a[i]);
    for(int i=1;i<=m;i++){
        read(typ);read(x);read(y);
        switch(typ){
            case 1:read(z);res=1;get_rank(1,1,n,x,y,z);printf("%d\n",res);break;
            case 2:read(z);get_index(x,y,z);break;
            case 3:change(1,1,n,x,y,a[x]);a[x]=y;break;
            case 4:read(z);res=0;ask_before(1,1,n,x,y,z);printf("%d\n",res);break;
            case 5:read(z);res=1e9;ask_after(1,1,n,x,y,z);printf("%d\n",res);break;
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/MikuKnight/p/9090142.html