P3380 模板二逼平衡树(树套树)
Posted qyj060604
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3380 模板二逼平衡树(树套树)相关的知识,希望对你有一定的参考价值。
P3380 【模板】二逼平衡树(树套树)
真是超级好玩
其实说白了,就是对于线段树每一个节点维护一个平衡树
STL依赖症,不能用,只得手写平衡树,真心累
学校里花了两节课,码完了238行,回家以后把操作二重复情况判断以后,一遍AC
这种题,就是:说起来好做,做起来......
代码:
#include<bits/stdc++.h> using namespace std; const int N=100005; const int MAXN=100005; int n,m; int a[MAXN]; struct Treap{ struct node{//结构体重建树 int l;//左儿子 int r;//右儿子 int k;//权值 int p;//优先级 int c;//重复元素个数 int s;//子节点个数 #define l(x) t[x].l #define r(x) t[x].r #define v(x) t[x].k #define p(x) t[x].p #define c(x) t[x].c #define s(x) t[x].s }t[N*20]; int cnty; int pooly; int n; int data; Treap(){pooly=0;cnty=0;} inline void upt(const int &k){//传递 s(k)=s(l(k))+s(r(k))+c(k); } inline void zig(int &k){//左旋 int y=l(k); l(k)=r(y); r(y)=k; s(y)=s(k); upt(k); k=y; } inline void zag(int &k){//右旋 int y=r(k); r(k)=l(y); l(y)=k; s(y)=s(k); upt(k); k=y; } inline void ins(int &k,const int &val){//插入节点 if(!k){//新建一个节点 k=++pooly; v(k)=val; p(k)=rand();//赋值一个随机的优先级 c(k)=s(k)=1; l(k)=r(k)=0;//没有左右儿子 return; } else ++s(k); if(v(k)==val) ++c(k);//有重复元素 else if(val<v(k)){ ins(l(k),val); if(p(l(k))<p(k)) zig(k);//左旋:维护堆性质 } else{ ins(r(k),val); if(p(r(k))<p(k)) zag(k);//右旋:维护堆性质 } } int Rk(int root,const int &val){ int x=root; int res=0; while(x){ if(val==v(x)) return res+s(l(x))+1;//找到了:返回排名 if(val<v(x)) x=l(x); else res+=s(l(x))+c(x),x=r(x); } } inline int serch_min(int root,const int &val){ int x=root,res=-2147483647; while(x){ if(v(x)<val) res=v(x),x=r(x); else x=l(x); } return res; } inline int serch_max(int root,const int &val){ int x=root,res=2147483647; while(x){ if(v(x)>val) res=v(x),x=l(x); else x=r(x); } return res; } inline int serch(int root,const int &val){ int x=root,res=0; while(x){ if(v(x)<val){ res+=c(x)+s(l(x)); x=r(x); } else{ x=l(x); } } return res; } inline int Kth(int root,int k){ int x=root; while(x){ if(s(l(x))<k&&s(l(x))+c(x)>=k) return v(x); if(s(l(x))>=k) x=l(x); else k-=s(l(x))+c(x),x=r(x); } return 0; } inline void del(int &k,const int &val){ if(v(k)==val){ if(c(k)>1) --c(k),--s(k); else if(!l(k)||!r(k)) k=l(k)+r(k); else if(p(l(k))<p(r(k))) zig(k),del(k,val); else zag(k),del(k,val); return; } --s(k); if(val<v(k)) del(l(k),val); else del(r(k),val); return; } }TP; struct Sugment_Tree{ #define il inline #define mid (l+r)/2 int root[N*8]; int ans; Sugment_Tree(){memset(root,0,sizeof(root));ans=0;} il void ins(int l,int r,int num,int pos,int val){ if(l>pos||r<pos) return; if(l==r&&r==pos){ TP.ins(root[num],val); return; } TP.ins(root[num],val); ins(l,mid,num<<1,pos,val); ins(mid+1,r,num<<1|1,pos,val); } il void del(int l,int r,int num,int pos,int val){ if(l>pos||r<pos) return; if(l==r&&r==pos){ TP.del(root[num],val); return; } TP.del(root[num],val); del(l,mid,num<<1,pos,val); del(mid+1,r,num<<1|1,pos,val); } il int ranking(int l,int r,int num,int L,int R,int val){ if(l>R||r<L) return 0; if(l>=L&&r<=R){ if(TP.serch_min(root[num],val)==-2147483647) return 0; return TP.serch(root[num],val); } return ranking(l,mid,num<<1,L,R,val)+ranking(mid+1,r,num<<1|1,L,R,val); } il int rpk(int l,int r,int num,int L,int R,int val){ return ranking(l,r,num,L,R,val)+1; } il int ask(int L,int R,int val){ int l=0,r=100000000,ans; while(l<=r){ if(rpk(1,n,1,L,R,mid)<=val) ans=mid,l=mid+1; else r=mid-1; } return ans; } il void pre(int l,int r,int num,int L,int R,int val){ if(l>R||r<L) return; if(l>=L&&r<=R){ ans=max(ans,TP.serch_min(root[num],val)); return; } pre(l,mid,num<<1,L,R,val); pre(mid+1,r,num<<1|1,L,R,val); } il int pre_ask(int L,int R,int val){ ans=-2147483647; pre(1,n,1,L,R,val); return ans; } il void suf(int l,int r,int num,int L,int R,int val){ if(l>R||r<L) return; if(l>=L&&r<=R){ ans=min(ans,TP.serch_max(root[num],val)); return; } suf(l,mid,num<<1,L,R,val); suf(mid+1,r,num<<1|1,L,R,val); } il int suf_ask(int L,int R,int val){ ans=2147483647; suf(1,n,1,L,R,val); return ans; } }T; int main(){ srand((unsigned)time(NULL)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]),T.ins(1,n,1,i,a[i]); //cout<<T.ranking(1,n,1,1,3,3)<<endl; while(m--){ int opt; scanf("%d",&opt); int l,r,val,pos; if(opt==1) { scanf("%d%d%d",&l,&r,&val); int p=T.rpk(1,n,1,l,r,val); printf("%d ",p); } else if(opt==2){ scanf("%d%d%d",&l,&r,&val); int p=T.ask(l,r,val); printf("%d ",p); } else if(opt==3){ scanf("%d%d",&pos,&val); T.del(1,n,1,pos,a[pos]); a[pos]=val; T.ins(1,n,1,pos,a[pos]); } else if(opt==4){ scanf("%d%d%d",&l,&r,&val); int p=T.pre_ask(l,r,val); printf("%d ",p); } else{ scanf("%d%d%d",&l,&r,&val); int p=T.suf_ask(l,r,val); printf("%d ",p); } } return 0; }
以上是关于P3380 模板二逼平衡树(树套树)的主要内容,如果未能解决你的问题,请参考以下文章