[树套树] BZOJ3196: 二逼平衡树
来源:互联网 发布:你的眼神网络歌手 编辑:程序博客网 时间:2024/05/21 09:42
题意
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)
题解
求区间第k大,树套树模板题。
外层线段树定序列,内层平衡树询问信息。
询问给定数的区间排名直接做就行了。复杂度
求区间排名为k的值还需要加一层二分答案,用上一问题验证。复杂度
不知道有没有复杂度更低的方法……
还要注意一下常数问题,其他的不必说了。
#include<cstdio>#include<cstdlib>const int maxn=50005;int max(int x,int y){ return x>y?x:y; }int min(int x,int y){ return x<y?x:y; }struct node{ node* ch[2]; int key,fix,size,cnt; node(){} node(int w,node* son){ key=w; ch[0]=ch[1]=son; fix=rand(); size=cnt=1; } void maintain(){ size=ch[0]->size + ch[1]->size + cnt; }};typedef node* P_node;struct Treap{ node nil; P_node root,null,len; Treap(){ root=null=&nil; null->size=null->cnt=0; null->ch[0]=null->ch[1]=null; } void rot(P_node &p,int d){ P_node k=p->ch[d^1]; p->ch[d^1]=k->ch[d]; k->ch[d]=p; p->maintain(); k->maintain(); p=k; } void _Insert(P_node &p,int tkey){ if(p==null) p=new node(tkey,null); else if(p->key==tkey) p->cnt++; else{ int d=tkey>p->key; _Insert(p->ch[d],tkey); if(p->ch[d]->fix > p->fix) rot(p,d^1); } p->maintain(); } void _Erase(P_node &p,int tkey){ if(p==null) return; if(p->key==tkey){ if(p->cnt>1) p->cnt--; else if(p->ch[0]==null||p->ch[1]==null){ P_node tem=p; p->ch[0]==null?p=p->ch[1]:p=p->ch[0]; delete tem; }else{ int d=p->ch[0]->fix > p->ch[1]->fix; rot(p,d); _Erase(p->ch[d],tkey); } } else _Erase(p->ch[tkey>p->key],tkey); p->maintain(); } int _Rank(P_node p,int tkey,int res){ if(p==null) return res+1; if(p->key==tkey) return p->ch[0]->size+res+1; if(tkey<p->key) return _Rank(p->ch[0],tkey,res); return _Rank(p->ch[1],tkey,res+ p->ch[0]->size + p->cnt); } int _Pred(P_node p,int tkey){ if(p==null) return -2147483647; if(tkey<=p->key) return _Pred(p->ch[0],tkey); return max(p->key,_Pred(p->ch[1],tkey)); } int _Succ(P_node p,int tkey){ if(p==null) return 2147483647; if(tkey>=p->key) return _Succ(p->ch[1],tkey); return min(p->key,_Succ(p->ch[0],tkey)); } void Insert(int tkey){ _Insert(root,tkey); } void Erase(int tkey){ _Erase(root,tkey); } int Rank(int tkey){ return _Rank(root,tkey,0); } int Pred(int tkey){ return _Pred(root,tkey); } int Succ(int tkey){ return _Succ(root,tkey); }};struct Segment{ int L,R; Segment(){ L=R=-1; } Treap T;} seg[maxn*4]; void Seg_Build(int p,int L,int R){ seg[p].L=L; seg[p].R=R; if(L==R) return; int mid=(L+R)>>1; Seg_Build(p<<1,L,mid); Seg_Build(p<<1|1,mid+1,R);}void Seg_Insert(int p,int pos,int tkey){ if(p>=4*maxn||seg[p].R<pos||pos<seg[p].L) return; if(seg[p].L<=pos&&pos<=seg[p].R) seg[p].T.Insert(tkey); Seg_Insert(p<<1,pos,tkey); Seg_Insert(p<<1|1,pos,tkey);}void Seg_Erase(int p,int pos,int tkey){ if(p>=4*maxn||seg[p].R<pos||pos<seg[p].L) return; if(seg[p].L<=pos&&pos<=seg[p].R) seg[p].T.Erase(tkey); Seg_Erase(p<<1,pos,tkey); Seg_Erase(p<<1|1,pos,tkey); }int Seg_Rank(int p,int L,int R,int tkey){ if(p>=4*maxn||seg[p].R<L||R<seg[p].L) return 0; if(L<=seg[p].L&&seg[p].R<=R) return seg[p].T.Rank(tkey)-1; return Seg_Rank(p<<1,L,R,tkey)+Seg_Rank(p<<1|1,L,R,tkey);}int Seg_Kth(int q_L,int q_R,int k){ int L=0,R=1e+8,res; while(L<=R){ int mid=(L+R)>>1; int rk=Seg_Rank(1,q_L,q_R,mid)+1; if(rk<=k) L=mid+1, res=mid; else R=mid-1; } return res;}int Seg_Pred(int p,int L,int R,int tkey){ if(p>=4*maxn||seg[p].R<L||R<seg[p].L) return -2147483647; if(L<=seg[p].L&&seg[p].R<=R) return seg[p].T.Pred(tkey); return max(Seg_Pred(p<<1,L,R,tkey),Seg_Pred(p<<1|1,L,R,tkey)); }int Seg_Succ(int p,int L,int R,int tkey){ if(p>=4*maxn||seg[p].R<L||R<seg[p].L) return 2147483647; if(L<=seg[p].L&&seg[p].R<=R) return seg[p].T.Succ(tkey); return min(Seg_Succ(p<<1,L,R,tkey),Seg_Succ(p<<1|1,L,R,tkey)); }int getint(){ char ch=getchar(); int res=0,ff=1; while(!('0'<=ch&&ch<='9')){ if(ch=='-') ff=-1; ch=getchar(); } while('0'<=ch&&ch<='9') res=res*10+ch-'0', ch=getchar(); return res*ff;}int n,m,a[maxn];int main(){ scanf("%d%d",&n,&m); Seg_Build(1,1,n); for(int i=1;i<=n;i++) Seg_Insert(1,i,a[i]=getint()); while(m--){ int pd=getint(); if(pd==1){ int x=getint(),y=getint(),z=getint(); printf("%d\n",Seg_Rank(1,x,y,z)+1); } else if(pd==2){ int x=getint(),y=getint(),z=getint(); printf("%d\n",Seg_Kth(x,y,z)); } else if(pd==3){ int x=getint(),y=getint(); Seg_Erase(1,x,a[x]); Seg_Insert(1,x,y); a[x]=y; } else if(pd==4){ int x=getint(),y=getint(),z=getint(); printf("%d\n",Seg_Pred(1,x,y,z)); } else if(pd==5){ int x=getint(),y=getint(),z=getint(); printf("%d\n",Seg_Succ(1,x,y,z)); } } return 0;}
0 0
- [树套树] BZOJ3196: 二逼平衡树
- bzoj3196 二逼平衡树
- Bzoj3196 二逼平衡树
- BZOJ3196 二逼平衡树
- 【bzoj3196】Tyvj 1730 二逼平衡树 树套树
- 树套树——BZOJ3196/Luogu3380 二逼平衡树
- [Bzoj3196]Tyvj 1730 二逼平衡树
- BZOJ3196 二逼平衡树 Solution
- BZOJ3196: Tyvj 1730 二逼平衡树
- bzoj3196 tyvj1730 二逼平衡树
- [BZOJ3196]Tyvj 1730 二逼平衡树
- BZOJ3196——二逼平衡树
- bzoj3196: Tyvj 1730 二逼平衡树
- bzoj3196: Tyvj 1730 二逼平衡树
- 【bzoj3196】Tyvj 1730 二逼平衡树
- bzoj3196 Tyvj 1730 二逼平衡树
- bzoj3196: Tyvj 1730 二逼平衡树
- bzoj3196 二逼平衡树 线段树套平衡树
- 2017年会是Serverless爆发之年吗?
- 序列化
- Linux 内核网络协议栈 ------sk_buff 结构体 以及 完全解释 (2.6.16)
- Java中使用try...catch以及try...catch...finally捕获异常
- spring_02国际化支持
- [树套树] BZOJ3196: 二逼平衡树
- 词向量之word2vec(1)
- MD5大概简述
- pyqtgraph如何设置字符串类型横坐标
- 谈谈移动硬盘或者手机连接到PC提示“无法访问,拒绝访问”或“您没有访问该设备的权限”的解决办法
- android 系统架构分析
- C++复习之友元和const修饰类成员
- Head First SQL 第五章
- PE文件结构图