【BZOJ】3196: Tyvj 1730 二逼平衡树-树套树

传送门:bzoj3196


代码

树套树模板,线段树套Treap。
卡常是因为本蒟蒻太菜了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define mid ((l+r)>>1)
using namespace std;
const int N=2e5+10;
const int M=5e6+10;
const int inf=1e8;
int n,m,ini[N],rt[N],mx;
int s[M],ls[M],rs[M],rnd[M],v[M],w[M];
int opt,l,r,pos,K,sz,tp,ans;
#ifdef ONLINE_JUDGE  
char *TT,*mo,but[(1<<15)+2];  
#define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin)),TT==mo)?0:*TT++)  
#endif 
inline int rd()
{
    char ch=getchar();int x=0,f=1;
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*f;
}
inline void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');} 

inline void update( int k){s[k]=s[rs[k]]+s[ls[k]]+w[k];}
inline void lturn(int &k)
{int t=rs[k];rs[k]=ls[t];ls[t]=k;update(k);k=t;update(k);}
inline void rturn(int &k)
{int t=ls[k];ls[k]=rs[t];rs[t]=k;update(k);k=t;update(k);}

inline void insert(int &root,int val)
{
    if(!root){root=++sz;s[root]=w[root]=1;v[root]=val;return;}
    s[root]++;if(val==v[root]){w[root]++;return;}
    if(v[root]>val){insert(ls[root],val);if(rnd[ls[root]]<rnd[root]) rturn(root);}
    else{insert(rs[root],val);if(rnd[rs[root]]<rnd[root]) lturn(root);}
}

inline void del(int &root,int val)
{
    if(v[root]==val){
        if(w[root]>1){w[root]--;s[root]--;return;}
        if(!ls[root] || !rs[root]){root=ls[root]+rs[root];return;}
        if(rnd[ls[root]]<rnd[root]) rturn(root);
        else lturn(root);del(root,val);
    }else { val<v[root]?del(ls[root],val):del(rs[root],val);s[root]--;}
}

inline void ad(int k,int l,int r,int pos,int val)
{
    insert(rt[k],val);
    if(l^r){
        pos<=mid? ad(k<<1,l,mid,pos,val):ad(k<<1|1,mid+1,r,pos,val);
    }
}

inline void get_rk(int k,int val)
{
    if(!k) return;
    if(!(v[k]^val)) tp+=s[ls[k]]; 
    else if(v[k]<val){tp+=s[ls[k]]+w[k];get_rk(rs[k],val);}
    else get_rk(ls[k],val);
}

inline void get_pre(int k,int val)
{
    if(!k) return;
    if(v[k]<val){tp=max(tp,v[k]);get_pre(rs[k],val);}
    else get_pre(ls[k],val);
}

inline void get_nxt(int k,int val)
{
    if(!k) return;
    if(v[k]>val){tp=min(tp,v[k]);get_nxt(ls[k],val);}
    else get_nxt(rs[k],val);
}

inline void q_rk(int k,int l,int r,int L,int R,int ss)
{
    if(l>=L && r<=R) get_rk(rt[k],ss);
    else{
        if(L<=mid) q_rk(k<<1,l,mid,L,R,ss);
        if(R>mid) q_rk(k<<1|1,mid+1,r,L,R,ss);
    }
}

inline void q_pre(int k,int l,int r,int L,int R,int val)
{
    if(l>=L && r<=R) get_pre(rt[k],val);
    else{
        if(L<=mid) q_pre(k<<1,l,mid,L,R,val);
        if(R>mid) q_pre(k<<1|1,mid+1,r,L,R,val);
    }
}

inline void q_nxt(int k,int l,int r,int L,int R,int val)
{
    if(l>=L && r<=R) get_nxt(rt[k],val);
    else{
        if(L<=mid) q_nxt(k<<1,l,mid,L,R,val);
        if(R>mid) q_nxt(k<<1|1,mid+1,r,L,R,val);
    }
}

inline void ask_rk(int l,int r,int k)
{tp=1;q_rk(1,1,n,l,r,k);print(tp);puts("");}
inline void ask_kth(int l,int r,int k)
{
    int L(0),R(mx);
    while(L<=R){
        int Mid=(L+R)>>1;
        tp=1;q_rk(1,1,n,l,r,Mid);
        if(tp<=k) L=(ans=Mid)+1;
        else R=Mid-1;
    }
    print(ans);puts("");
}
inline void change(int k,int l,int r,int pos,int ori,int now)
{
    del(rt[k],ori);insert(rt[k],now);
    if(l^r){
        if(pos<=mid) change(k<<1,l,mid,pos,ori,now);
        else change(k<<1|1,mid+1,r,pos,ori,now);
    }
}
inline void ask_pre(int l,int r,int k)
{tp=0;q_pre(1,1,n,l,r,k);print(tp);puts("");}
inline void ask_nxt(int l,int r,int k)
{tp=inf;q_nxt(1,1,n,l,r,k);print(tp);puts("");}

int main(){
    n=rd();m=rd();
    for(int i(1);i<=n;++i) {ini[i]=rd();mx=max(ini[i],mx);ad(1,1,n,i,ini[i]);}
    while(m--){
        switch(opt=rd()){
            case 1:l=rd(),r=rd(),K=rd();ask_rk(l,r,K);break;
            case 2:l=rd(),r=rd(),K=rd();ask_kth(l,r,K);break;
            case 3:pos=rd();K=rd();mx=max(K,mx);change(1,1,n,pos,ini[pos],K);ini[pos]=K;break;
            case 4:l=rd(),r=rd(),K=rd();ask_pre(l,r,K);break;
            case 5:l=rd(),r=rd(),K=rd();ask_nxt(l,r,K);break;
        }       
    } 
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值