1. 程式人生 > 其它 >[模板]二逼平衡樹(樹套樹)

[模板]二逼平衡樹(樹套樹)

#include<cstdio>
#include<cstring>
#include<string>
#define int long long
#define WR WinterRain
#define Combo void//RIP
using namespace std;
const int WR=10010000,INF=2147483647;
int n,m;
int a[WR];
struct Treap_Tree{
    struct BalanceTree{
        int val,sze,rnk,ch[2],cnt;
    }tree[WR];
    
int tot=0,root=1; Combo pushup(int k){ tree[k].sze=tree[tree[k].ch[0]].sze+tree[tree[k].ch[1]].sze+tree[k].cnt; } int add_point(int v){ tree[++tot].val=v; tree[tot].rnk=rand(); tree[tot].sze=tree[tot].cnt=1; tree[tot].ch[0]=tree[tot].ch[1]=0; return
tot; } Combo rotat(int &id,int dir){ int tmp=tree[id].ch[dir^1]; tree[id].ch[dir^1]=tree[tmp].ch[dir]; tree[tmp].ch[dir]=id; id=tmp; pushup(tree[id].ch[dir]),pushup(id); } Combo insrt(int &id,int v){ if(!id){ id=add_point(v);
return; } if(v==tree[id].val) tree[id].cnt++; else{ int dir; if(v<tree[id].val) dir=0; else dir=1; insrt(tree[id].ch[dir],v); if(tree[id].rnk<tree[tree[id].ch[dir]].rnk) rotat(id,dir^1); } pushup(id); } Combo remov(int &id,int v){ if(!id) return; if(v==tree[id].val){ if(tree[id].cnt>1){ tree[id].cnt--; pushup(id); return; } if(tree[id].ch[0]||tree[id].ch[1]){ if(!tree[id].ch[1]||tree[tree[id].ch[0]].rnk>tree[tree[id].ch[1]].rnk){ rotat(id,1);remov(tree[id].ch[1],v); }else{ rotat(id,0);remov(tree[id].ch[0],v); } pushup(id); return; } id=0;return; } if(v<tree[id].val) remov(tree[id].ch[0],v); else remov(tree[id].ch[1],v); pushup(id); } int get_rank(int id,int v){ if(!id) return 0; //printf("%d %d\n",id,v); if(v==tree[id].val) return tree[tree[id].ch[0]].sze; if(v<tree[id].val) return get_rank(tree[id].ch[0],v); else return get_rank(tree[id].ch[1],v)+tree[id].cnt+tree[tree[id].ch[0]].sze; } int get_val(int id,int rk){ if(!id) return INF; if(rk<=tree[tree[id].ch[0]].sze) return get_val(tree[id].ch[0],rk); else if(rk<=tree[id].cnt+tree[tree[id].ch[0]].sze) return tree[id].val; else return get_val(tree[id].ch[1],rk-tree[tree[id].ch[0]].sze-tree[id].cnt); } int get_pre(int id,int v){ int pre=-INF; while(id){ if(tree[id].val<v) pre=tree[id].val,id=tree[id].ch[1]; else id=tree[id].ch[0]; } return pre; } int get_nxt(int id,int v){ int nxt=INF; while(id){ if(tree[id].val>v) nxt=tree[id].val,id=tree[id].ch[0]; else id=tree[id].ch[1]; } //printf("%d\n\n",nxt); return nxt; } }treap; struct Segment_Tree{ struct SegmentTree{ int l,r,root; }tree[WR]; Combo build(int k,int l,int r){ tree[k].l=l,tree[k].r=r; for(int i=l;i<=r;i++) treap.insrt(tree[k].root,a[i]); if(l==r) return; int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); } Combo modify(int k,int pos,int v){ treap.remov(tree[k].root,a[pos]); treap.insrt(tree[k].root,v); if(tree[k].l==tree[k].r) return; int mid=(tree[k].l+tree[k].r)>>1; if(pos<=mid) modify(k<<1,pos,v); else modify(k<<1|1,pos,v); } int get_rank(int k,int l,int r,int v){ //printf("%d %d %d %d %d %d\n",k,tree[k].l,tree[k].r,l,r,tree[k].root); if(tree[k].l>r||tree[k].r<l) return 0; if(tree[k].l>=l&&tree[k].r<=r) return treap.get_rank(tree[k].root,v); else return get_rank(k<<1,l,r,v)+get_rank(k<<1|1,l,r,v); } int get_num(int st,int ed,int v){ int l=0,r=1e8; while(l<r){ int mid=(l+r+1)>>1; //printf("%d\n",get_rank(1,st,ed,mid)); if(get_rank(1,st,ed,mid)<v) l=mid; else r=mid-1; } return r; } int get_pre(int k,int l,int r,int v){ if(tree[k].l>r||tree[k].r<l) return -INF; if(tree[k].l>=l&&tree[k].r<=r) return treap.get_pre(tree[k].root,v); else return max(get_pre(k<<1,l,r,v),get_pre(k<<1|1,l,r,v)); } int get_nxt(int k,int l,int r,int v){ //printf("%d %d %d %d\n",k,tree[k].l,tree[k].r,v); if(tree[k].l>r||tree[k].r<l) return INF; if(tree[k].l>=l&&tree[k].r<=r) return treap.get_nxt(tree[k].root,v); else return min(get_nxt(k<<1,l,r,v),get_nxt(k<<1|1,l,r,v)); } }segment; int read(){ int s=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=(s<<1)+(s<<3)+ch-48; ch=getchar(); } return s*w; } signed main(){ n=read(),m=read(); for(int i=1;i<=n;i++) a[i]=read(); segment.build(1,1,n); for(int i=1;i<=m;i++){ int opt=read(); if(opt==1){ int l=read(),r=read(),v=read(); printf("%lld\n",segment.get_rank(1,l,r,v)+1); } if(opt==2){ int l=read(),r=read(),v=read(); printf("%lld\n",segment.get_num(l,r,v)); } if(opt==3){ int pos=read(),x=read(); segment.modify(1,pos,x); a[pos]=x; } if(opt==4){ int l=read(),r=read(),v=read(); printf("%lld\n",segment.get_pre(1,l,r,v)); } if(opt==5){ int l=read(),r=read(),v=read(); printf("%lld\n",segment.get_nxt(1,l,r,v)); } } return 0; }