bzoj3196 Tyvj 1730 二逼平衡树(树套树,线段树套splay/bit套动态开点线段树)
2018-02-25 22:27
411 查看
线段树套splay,看网上题解大部分说套splay是过不去的,需要优越的姿势才可以,本想着过不去再卡一卡优越的姿势的,然而过了qaq。
线段树维护区间,对于线段树的每个节点我们吊一棵splay维护区间内的权值。
操作1:查询k在区间[l,r]上的排名。
线段树上查询区间,去splay上查询小于k的有多少个,都加起来即可,再加1就是k的排名。
操作2:查询区间[l,r]上的排名为k的数。
这个操作比较精妙,我们先二分答案,然后去查mid的排名,调整答案即可。
操作3:修改x的权值为val。
相当于线段树单点修改,把原来的删了,再ins新的进去即可。
操作4:查询区间[l,r]上的k的前驱。
线段树上查询区间,去splay上查前驱,取max即可。
操作5:查询区间[l,r]上的k的后继。
线段树上查询区间,去splay上查后继,取min即可。
空间复杂度O((n+m)logn)O((n+m)logn)或者O(nlogn)O(nlogn)
操作2是O(logwlog2n)的吧,其它操作都是O(log2n)O(logwlog2n)的吧,其它操作都是O(log2n)
时间复杂度O(mlog2nlogw)O(mlog2nlogw)
不过为什么大家都说是O(nlog2n)O(nlog2n)的呢(迷
tips:要注意重复权值的处理哟,和普通平衡树一样的处理就好了
2.26upd: 树状数组套动态开点线段树
本以为空间怎么算都是过不去的,然而大家都说离散化权值以后,最多8e6的就够了。蒟蒻算了算树状数组所需的节点个数,好像确实比nlogn要少一半左右。动态开点线段树新建一条链均摊下来应该也要比logn小一些。但是具体能卡到多少并不是很会。
能开的下的话就很好做了,常数也很小。类似bzoj1901
2.28upd:写了一下线段树套treap,确实比splay快一些。
线段树维护区间,对于线段树的每个节点我们吊一棵splay维护区间内的权值。
操作1:查询k在区间[l,r]上的排名。
线段树上查询区间,去splay上查询小于k的有多少个,都加起来即可,再加1就是k的排名。
操作2:查询区间[l,r]上的排名为k的数。
这个操作比较精妙,我们先二分答案,然后去查mid的排名,调整答案即可。
操作3:修改x的权值为val。
相当于线段树单点修改,把原来的删了,再ins新的进去即可。
操作4:查询区间[l,r]上的k的前驱。
线段树上查询区间,去splay上查前驱,取max即可。
操作5:查询区间[l,r]上的k的后继。
线段树上查询区间,去splay上查后继,取min即可。
空间复杂度O((n+m)logn)O((n+m)logn)或者O(nlogn)O(nlogn)
操作2是O(logwlog2n)的吧,其它操作都是O(log2n)O(logwlog2n)的吧,其它操作都是O(log2n)
时间复杂度O(mlog2nlogw)O(mlog2nlogw)
不过为什么大家都说是O(nlog2n)O(nlog2n)的呢(迷
tips:要注意重复权值的处理哟,和普通平衡树一样的处理就好了
2.26upd: 树状数组套动态开点线段树
本以为空间怎么算都是过不去的,然而大家都说离散化权值以后,最多8e6的就够了。蒟蒻算了算树状数组所需的节点个数,好像确实比nlogn要少一半左右。动态开点线段树新建一条链均摊下来应该也要比logn小一些。但是具体能卡到多少并不是很会。
能开的下的话就很好做了,常数也很小。类似bzoj1901
2.28upd:写了一下线段树套treap,确实比splay快一些。
线段树套splay
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define ll long long #define inf 2147483647 #define N 50010 inline char gc(){ static char buf[1<<16],*S,*T; if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;} return *S++; } inline int read(){ int x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f; } int n,m,a ,rt[N<<2],fa[N*40],c[N*40][2],v[N*40],sz[N*40],cnt[N*40],owo=0; int pos ,mx=0,ans; inline void update(int x){ int l=c[x][0],r=c[x][1]; sz[x]=sz[l]+sz[r]+cnt[x]; } inline void rotate(int x,int &k){ int y=fa[x],z=fa[y],l=x==c[y][1],r=l^1; if(y==k) k=x; else c[z][y==c[z][1]]=x; fa[c[x][r]]=y;fa[y]=x;fa[x]=z; c[y][l]=c[x][r];c[x][r]=y;update(y);update(x); } inline void splay(int x,int &k){ while(x!=k){ int y=fa[x],z=fa[y]; if(y!=k){ if(x==c[y][1]^y==c[z][1]) rotate(x,k); else rotate(y,k); }rotate(x,k); } } inline int find(int p,int x){ if(v[p]==x) return p; if(x<v[p]) return find(c[p][0],x); return find(c[p][1],x); } inline void ins(int &p,int x,int Fa,int id){ if(!p){ p=++owo;fa[p]=Fa;c[p][0]=c[p][1]=0;v[p]=x;sz[p]=cnt[p]=1;splay(p,rt[id]);return; }if(v[p]==x){cnt[p]++;sz[p]++;splay(p,rt[id]);return;} if(x<v[p]) ins(c[p][0],x,p,id); else ins(c[p][1],x,p,id); } inline int qrank(int p,int x){//查询比x小的数有几个 if(!p) return 0; if(x<v[p]) return qrank(c[p][0],x); if(x==v[p]) return sz[c[p][0]]; return sz[c[p][0]]+cnt[p]+qrank(c[p][1],x); } inline void del(int id,int val){ int x=find(rt[id],val);splay(x,rt[id]); if(cnt[x]>1){cnt[x]--;sz[x]--;return;} if(c[x][0]*c[x][1]==0){ rt[id]=c[x][0]+c[x][1];fa[rt[id]]=c[x][0]=c[x][1]=0;return; }int pre=c[x][0],succ=c[x][1]; while(c[pre][1]) pre=c[pre][1];while(c[succ][0]) succ=c[succ][0]; splay(pre,rt[id]);splay(succ,c[pre][1]);c[succ][0]=fa[x]=0; update(succ);update(pre); } inline int getpre(int rt,int x){ int res=-inf,p=rt; while(p){ if(v[p]<x) res=v[p],p=c[p][1]; else p=c[p][0]; }return res; } inline int getsucc(int rt,int x){ int res=inf,p=rt; while(p){ if(v[p]>x) res=v[p],p=c[p][0]; else p=c[p][1]; }return res; } inline void seg_ins(int p,int l,int r,int x,int val){ ins(rt[p],val,0,p); if(l==r) return;int mid=l+r>>1; if(x<=mid) seg_ins(p<<1,l,mid,x,val); else seg_ins(p<<1|1,mid+1,r,x,val); } inline int seg_rank(int p,int l,int r,int x,int y,int val){ if(x<=l&&r<=y) return qrank(rt[p],val); int mid=l+r>>1,res=0; if(x<=mid) res+=seg_rank(p<<1,l,mid,x,y,val); if(y>mid) res+=seg_rank(p<<1|1,mid+1,r,x,y,val); return res; } inline void seg_change(int p,int l,int r,int x,int val){ del(p,a[x]);ins(rt[p],val,0,p); if(l==r) return;int mid=l+r>>1; if(x<=mid) seg_change(p<<1,l,mid,x,val); else seg_change(p<<1|1,mid+1,r,x,val); } inline int getkth(int x,int y,int k){ int l=0,r=mx; while(l<=r){ int mid=l+r>>1; if(seg_rank(1,1,n,x,y,mid)<k) l=mid+1; else r=mid-1; }return l-1; } inline void seg_pre(int p,int l,int r,int x,int y,int val){ if(x<=l&&r<=y){ans=max(ans,getpre(rt[p],val));return;} int mid=l+r>>1; if(x<=mid) seg_pre(p<<1,l,mid,x,y,val); if(y>mid) seg_pre(p<<1|1,mid+1,r,x,y,val); } inline void seg_succ(int p,int l,int r,int x,int y,int val){ if(x<=l&&r<=y){ans=min(ans,getsucc(rt[p],val));return;} int mid=l+r>>1; if(x<=mid) seg_succ(p<<1,l,mid,x,y,val); if(y>mid) seg_succ(p<<1|1,mid+1,r,x,y,val); } int main(){ // freopen("a.in","r",stdin); n=read();m=read(); for(int i=1;i<=n;++i) a[i]=read(),seg_ins(1,1,n,i,a[i]),mx=max(mx,a[i]); while(m--){ int op=read(); if(op==3){int x=read(),val=read();seg_change(1,1,n,x,val);a[x]=val;mx=max(mx,val);continue;} int l=read(),r=read(),k=read(); if(op==1) printf("%d\n",seg_rank(1,1,n,l,r,k)+1); if(op==2) printf("%d\n",getkth(l,r,k)); if(op==4){ans=-inf;seg_pre(1,1,n,l,r,k);printf("%d\n",ans);} if(op==5){ans=inf;seg_succ(1,1,n,l,r,k);printf("%d\n",ans);} }return 0; }
树状数组套动态开点线段树
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define ll long long #define inf 2147483647 #define N 50010 inline char gc(){ static char buf[1<<16],*S,*T; if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;} return *S++; } inline int read(){ int x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f; } int n,m,aa[N<<1],a ,rt ,num=0,owo=0,p1 ,p2 ,n1,n2; struct node{ int lc,rc,sum; }tr[N*80*2]; struct oper{ int op,l,r,k; }e ; inline void add(int &p,int l,int r,int x,int val){ if(!p) p=++owo;tr[p].sum+=val; if(l==r) return;int mid=l+r>>1; if(x<=mid) add(tr[p].lc,l,mid,x,val); else add(tr[p].rc,mid+1,r,x,val); } inline void bit_add(int x,int pos,int val){ for(;x<=n;x+=x&-x) add(rt[x],1,num,pos,val); } inline void gao1(int x){ n1=0;for(;x;x-=x&-x) p1[++n1]=rt[x]; } inline void gao2(int x){ n2=0;for(;x;x-=x&-x) p2[++n2]=rt[x]; } inline int qless(int l,int r,int x){ if(l==r) return 0; int mid=l+r>>1,res=0; if(x<=mid){ for(int i=1;i<=n1;++i) p1[i]=tr[p1[i]].lc; for(int i=1;i<=n2;++i) p2[i]=tr[p2[i]].lc; return qless(l,mid,x); }else{ for(int i=1;i<=n1;++i) res+=tr[tr[p1[i]].lc].sum; for(int i=1;i<=n2;++i) res-=tr[tr[p2[i]].lc].sum; for(int i=1;i<=n1;++i) p1[i]=tr[p1[i]].rc; for(int i=1;i<=n2;++i) p2[i]=tr[p2[i]].rc; return res+qless(mid+1,r,x); } } inline int qmore(int l,int r,int x){ if(l==r) return 0; int mid=l+r>>1,res=0; if(x<mid+1){ for(int i=1;i<=n1;++i) res+=tr[tr[p1[i]].rc].sum; for(int i=1;i<=n2;++i) res-=tr[tr[p2[i]].rc].sum; for(int i=1;i<=n1;++i) p1[i]=tr[p1[i]].lc; for(int i=1;i<=n2;++i) p2[i]=tr[p2[i]].lc; return res+qmore(l,mid,x); }else{ for(int i=1;i<=n1;++i) p1[i]=tr[p1[i]].rc; for(int i=1;i<=n2;++i) p2[i]=tr[p2[i]].rc; return qmore(mid+1,r,x); } } inline int qkth(int l,int r,int k){ if(l==r) return l; int res=0,mid=l+r>>1; for(int i=1;i<=n1;++i) res+=tr[tr[p1[i]].lc].sum; for(int i=1;i<=n2;++i) res-=tr[tr[p2[i]].lc].sum; if(k<=res){ for(int i=1;i<=n1;++i) p1[i]=tr[p1[i]].lc; for(int i=1;i<=n2;++i) p2[i]=tr[p2[i]].lc; return qkth(l,mid,k); } for(int i=1;i<=n1;++i) p1[i]=tr[p1[i]].rc; for(int i=1;i<=n2;++i) p2[i]=tr[p2[i]].rc; return qkth(mid+1,r,k-res); } int main(){ // freopen("a.in","r",stdin); n=read();m=read();num=n; for(int i=1;i<=n;++i) aa[i]=a[i]=read(); for(int i=1;i<=m;++i){ e[i].op=read();e[i].l=read();e[i].r=read(); if(e[i].op==3){aa[++num]=e[i].r;continue;} e[i].k=read();if(e[i].op!=2) aa[++num]=e[i].k; }sort(aa+1,aa+num+1);num=unique(aa+1,aa+num+1)-aa-1; for(int i=1;i<=n;++i) a[i]=lower_bound(aa+1,aa+num+1,a[i])-aa,bit_add(i,a[i],1); for(int i=1;i<=m;++i){ if(e[i].op==1){ e[i].k=lower_bound(aa+1,aa+num+1,e[i].k)-aa; gao1(e[i].r);gao2(e[i].l-1); printf("%d\n",qless(1,num,e[i].k)+1);continue; }if(e[i].op==2){ gao1(e[i].r);gao2(e[i].l-1); printf("%d\n",aa[qkth(1,num,e[i].k)]);continue; }if(e[i].op==3){ e[i].r=lower_bound(aa+1,aa+num+1,e[i].r)-aa; int x=e[i].l;bit_add(x,a[x],-1); a[x]=e[i].r;bit_add(x,a[x],1);continue; }if(e[i].op==4){ e[i].k=lower_bound(aa+1,aa+num+1,e[i].k)-aa; gao1(e[i].r);gao2(e[i].l-1); int pos=qless(1,num,e[i].k); if(!pos){printf("%d\n",-inf);continue;} gao1(e[i].r);gao2(e[i].l-1); printf("%d\n",aa[qkth(1,num,pos)]);continue; }if(e[i].op==5){ e[i].k=lower_bound(aa+1,aa+num+1,e[i].k)-aa; gao1(e[i].r);gao2(e[i].l-1); int pos=qmore(1,num,e[i].k),sz=e[i].r-e[i].l+1; if(!pos){printf("%d\n",inf);continue;} gao1(e[i].r);gao2(e[i].l-1); printf("%d\n",aa[qkth(1,num,sz-pos+1)]);continue; } }return 0; }
线段树套treap
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define ll long long #define inf 2147483647 #define N 50010 inline char gc(){ static char buf[1<<16],*S,*T; if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;} return *S++; } inline int read(){ int x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f; } int n,m,a ,rt[N<<2],ls[N*40],rs[N*40],v[N*40],sz[N*40],cnt[N*40],rnd[N*40],owo=0; int pos ,mx=0,ans; inline void update(int p){sz[p]=sz[ls[p]]+sz[rs[p]]+cnt[p];} inline void rturn(int &y){int x=ls[y];ls[y]=rs[x];rs[x]=y;update(y);update(x);y=x;} inline void lturn(int &y){int x=rs[y];rs[y]=ls[x];ls[x]=y;update(y);update(x);y=x;} inline void ins(int &p,int x){ if(!p){p=++owo;v[p]=x;sz[p]=cnt[p]=1;rnd[p]=rand();return;} if(v[p]==x){cnt[p]++;sz[p]++;return;}++sz[p]; if(x<v[p]){ins(ls[p],x);if(rnd[ls[p]]<rnd[p]) rturn(p);} else {ins(rs[p],x);if(rnd[rs[p]]<rnd[p]) lturn(p);} } inline int qrank(int p,int x){//查询比x小的数有几个 if(!p) return 0; if(x<v[p]) return qrank(ls[p],x); if(x==v[p]) return sz[ls[p]]; return sz[ls[p]]+cnt[p]+qrank(rs[p],x); } inline void del(int &p,int x){ if(v[p]==x){ if(cnt[p]>1) cnt[p]--,sz[p]--; else if(ls[p]*rs[p]==0) p=ls[p]+rs[p]; else if(rnd[ls[p]]<rnd[rs[p]]) rturn(p),del(p,x); else lturn(p),del(p,x);return; }sz[p]--; if(x<v[p]) del(ls[p],x); else del(rs[p],x); } inline int getpre(int rt,int x){ int res=-inf,p=rt; while(p){ if(v[p]<x) res=v[p],p=rs[p]; else p=ls[p]; }return res; } inline int getsucc(int rt,int x){ int res=inf,p=rt; while(p){ if(v[p]>x) res=v[p],p=ls[p]; else p=rs[p]; }return res; } inline void seg_ins(int p,int l,int r,int x,int val){ ins(rt[p],val); if(l==r) return;int mid=l+r>>1; if(x<=mid) seg_ins(p<<1,l,mid,x,val); else seg_ins(p<<1|1,mid+1,r,x,val); } inline int seg_rank(int p,int l,int r,int x,int y,int val){ if(x<=l&&r<=y) return qrank(rt[p],val); int mid=l+r>>1,res=0; if(x<=mid) res+=seg_rank(p<<1,l,mid,x,y,val); if(y>mid) res+=seg_rank(p<<1|1,mid+1,r,x,y,val); return res; } inline void seg_change(int p,int l,int r,int x,int val){ del(rt[p],a[x]);ins(rt[p],val); if(l==r) return;int mid=l+r>>1; if(x<=mid) seg_change(p<<1,l,mid,x,val); else seg_change(p<<1|1,mid+1,r,x,val); } inline int getkth(int x,int y,int k){ int l=0,r=mx; while(l<=r){ int mid=l+r>>1; if(seg_rank(1,1,n,x,y,mid)<k) l=mid+1; else r=mid-1; }return l-1; } inline void seg_pre(int p,int l,int r,int x,int y,int val){ if(x<=l&&r<=y){ans=max(ans,getpre(rt[p],val));return;} int mid=l+r>>1; if(x<=mid) seg_pre(p<<1,l,mid,x,y,val); if(y>mid) seg_pre(p<<1|1,mid+1,r,x,y,val); } inline void seg_succ(int p,int l,int r,int x,int y,int val){ if(x<=l&&r<=y){ans=min(ans,getsucc(rt[p],val));return;} int mid=l+r>>1; if(x<=mid) seg_succ(p<<1,l,mid,x,y,val); if(y>mid) seg_succ(p<<1|1,mid+1,r,x,y,val); } int main(){ // freopen("a.in","r",stdin); n=read();m=read();srand(20000712); for(int i=1;i<=n;++i) a[i]=read(),seg_ins(1,1,n,i,a[i]),mx=max(mx,a[i]); while(m--){ int op=read(); if(op==3){int x=read(),val=read();seg_change(1,1,n,x,val);a[x]=val;mx=max(mx,val);continue;} int l=read(),r=read(),k=read(); if(op==1) printf("%d\n",seg_rank(1,1,n,l,r,k)+1); if(op==2) printf("%d\n",getkth(l,r,k)); if(op==4){ans=-inf;seg_pre(1,1,n,l,r,k);printf("%d\n",ans);} if(op==5){ans=inf;seg_succ(1,1,n,l,r,k);printf("%d\n",ans);} }return 0; }
相关文章推荐
- BZOJ 3196 Tyvj 1730 二逼平衡树 线段树套splay
- bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】
- [BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)
- bzoj 3196: Tyvj 1730 二逼平衡树 线段树套splay
- BZOJ 3196 Tyvj 1730 二逼平衡树(线段树套treap)
- bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)
- BZOJ 3196: Tyvj 1730 二逼平衡树|线段树套平衡树
- 【bzoj3196】【坑】Tyvj 1730 二逼平衡树 线段树套Treap/Splay
- [bzoj3196][Tyvj 1730][二逼平衡树] (线段树套treap)
- bzoj3196 Tyvj 1730 二逼平衡树 线段树套treap
- 【bzoj3196】Tyvj 1730 二逼平衡树 线段树套Treap
- 【BZOJ3196】Tyvj 1730 二逼平衡树 线段树套Treap
- bzoj3196 [TYVJ1730]二逼平衡树 树套树 线段树套替罪羊树
- BZOJ 3196(Tyvj 1730 二逼平衡树-线段树套Treap)
- BZOJ3196: Tyvj 1730 二逼平衡树 (线段树 + Treap 练习题)
- BZOJ 3196 Tyvj 1730 二逼平衡树
- [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树
- [BZOJ 3196]Tyvj 1730 二逼平衡树
- bzoj 3196 Tyvj 1730 二逼平衡树(主席树)
- 【BZOJ】3196 Tyvj 1730 二逼平衡树 线段树+平衡树