首页 > 代码库 > Bzoj3196 Tyvj 1730 二逼平衡树
Bzoj3196 Tyvj 1730 二逼平衡树
Submit: 3350 Solved: 1324
Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)
Input
第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继
Output
对于操作1,2,4,5各输出一行,表示查询结果
Sample Input
9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5
Sample Output
2
4
3
4
9
4
3
4
9
HINT
1.n和m的数据范围:n,m<=50000
2.序列中每个数的数据范围:[0,1e8]
3.虽然原题没有,但事实上5操作的k可能为负数
Source
树套树
线段树套平衡树(treap)
外层线段树维护区间,内层treap维护该区间内的数值
代码超长看着就累
Bzoj过了,Tyvj上最后两个点过不去,迷
标题仿佛在嘲笑那些光写平衡树的人,又仿佛在嘲讽我这种模板题调一下午的人……
小发现:对拍的时候,要是每次错得不一样,基本上可以确定是旋转错了/结点删错了
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdlib> 6 #include<ctime> 7 using namespace std; 8 const int mxn=50010; 9 int read(){ 10 int x=0,f=1;char ch=getchar(); 11 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 12 while(ch>=‘0‘ && ch<=‘9‘){x=x*10-‘0‘+ch;ch=getchar();} 13 return x*f; 14 } 15 int n,m,root[mxn<<2]; 16 struct node{ 17 int l,r;int w,rand;int cnt,size; 18 }t[mxn*60]; 19 int cnt=0; 20 void pushup(int rt){ 21 t[rt].size=t[t[rt].l].size+t[t[rt].r].size+t[rt].cnt;return; 22 } 23 void lturn(int &rt){ 24 int tmp=t[rt].r; 25 t[rt].r=t[tmp].l; t[tmp].l=rt; 26 t[tmp].size=t[rt].size; 27 pushup(rt); rt=tmp; 28 return; 29 } 30 void rturn(int &rt){ 31 int tmp=t[rt].l; 32 t[rt].l=t[tmp].r; t[tmp].r=rt; 33 t[tmp].size=t[rt].size; 34 pushup(rt); rt=tmp; 35 return; 36 } 37 void insert(int w,int &rt){ 38 if(!rt){ 39 rt=++cnt; 40 t[rt].l=t[rt].r=0; 41 t[rt].size=t[rt].cnt=1; 42 t[rt].rand=rand(); 43 t[rt].w=w; 44 return; 45 } 46 t[rt].size++; 47 if(t[rt].w==w){t[rt].cnt++;return;} 48 if(w<t[rt].w){insert(w,t[rt].l);if(t[t[rt].l].rand>t[rt].rand)rturn(rt);} 49 else {insert(w,t[rt].r);if(t[t[rt].r].rand>t[rt].rand)lturn(rt);} 50 return; 51 } 52 void Del(int w,int &rt){ 53 if(t[rt].w==w){ 54 if(t[rt].cnt>1){t[rt].cnt--;t[rt].size--;return;} 55 if(t[rt].l*t[rt].r==0)rt=t[rt].l+t[rt].r; 56 else 57 if(t[t[rt].l].rand>t[t[rt].r].rand) 58 {rturn(rt);Del(w,rt);} 59 else{lturn(rt);Del(w,rt);}//开始写成Del(w,t[rt].l) WA了 60 return; 61 } 62 else if(w>t[rt].w)Del(w,t[rt].r); 63 else Del(w,t[rt].l); 64 t[rt].size--; 65 return; 66 } 67 // 68 void Build(int p,int v,int l,int r,int rt){ 69 insert(v,root[rt]); 70 if(l==r)return; 71 int mid=(l+r)>>1; 72 if(p<=mid)Build(p,v,l,mid,rt<<1); 73 else Build(p,v,mid+1,r,rt<<1|1); 74 return; 75 } 76 void update(int p,int last,int v,int l,int r,int rt){//改变某位置的值 77 // printf("p:%d last:%d v:%d l:%d r:%d rt:%d\n",p,last,v,l,r,rt); 78 Del(last,root[rt]);//删除旧值 79 insert(v,root[rt]);//添加新值 80 if(l==r)return; 81 int mid=(l+r)>>1; 82 if(p<=mid)update(p,last,v,l,mid,rt<<1); 83 else update(p,last,v,mid+1,r,rt<<1|1); 84 return; 85 } 86 // 87 int rank1(int w,int rt){ 88 if(!rt)return 0; 89 if(w==t[rt].w){return t[t[rt].l].size;} 90 if(w<t[rt].w)return rank1(w,t[rt].l); 91 else return t[t[rt].l].size+t[rt].cnt+rank1(w,t[rt].r); 92 } 93 int Qrk(int L,int R,int num,int l,int r,int rt){//查找num的排名 94 if(L<=l && r<=R)return rank1(num,root[rt]); 95 int mid=(l+r)>>1; 96 int res=0; 97 if(L<=mid)res+=Qrk(L,R,num,l,mid,rt<<1); 98 if(R>mid)res+=Qrk(L,R,num,mid+1,r,rt<<1|1); 99 return res;100 }101 int Qnum(int L,int R,int k){//查找排名为k的数 102 int l=0,r=1e9,ans=0;103 while(l<=r){//二分答案 104 int mid=(l+r)>>1;105 int res=Qrk(L,R,mid,1,n,1)+1;106 if(res<=k){l=mid+1;ans=mid;}107 else r=mid-1;108 }109 return ans;110 }111 int res=0;//存储前驱/后继答案112 void Pre(int w,int rt){113 if(!rt)return;114 if(t[rt].w<w){res=max(res,t[rt].w);Pre(w,t[rt].r);}115 else Pre(w,t[rt].l);116 return;117 }118 void Sub(int w,int rt){119 if(!rt)return;120 if(t[rt].w>w){res=min(res,t[rt].w);Sub(w,t[rt].l);}121 else Sub(w,t[rt].r);122 return;123 }124 void Qpre(int L,int R,int num,int l,int r,int rt){125 if(L<=l && r<=R){Pre(num,root[rt]);return;}126 int mid=(l+r)>>1;127 if(L<=mid)Qpre(L,R,num,l,mid,rt<<1);128 if(R>mid)Qpre(L,R,num,mid+1,r,rt<<1|1);129 return;130 }131 void Qsub(int L,int R,int num,int l,int r,int rt){132 // printf("!\n");133 if(L<=l && r<=R){Sub(num,root[rt]);return;}134 int mid=(l+r)>>1;135 if(L<=mid)Qsub(L,R,num,l,mid,rt<<1);136 if(R>mid)Qsub(L,R,num,mid+1,r,rt<<1|1);137 return;138 }139 int a[mxn];140 int main(){141 int i,j,x,y,w;142 n=read();m=read();143 srand(time(0));144 for(i=1;i<=n;i++){a[i]=read();Build(i,a[i],1,n,1);}145 int op;146 while(m--){147 op=read();148 switch(op){149 case 1:{150 x=read();y=read();w=read();151 printf("%d\n",Qrk(x,y,w,1,n,1)+1);152 break;153 }154 case 2:{155 x=read();y=read();w=read();156 printf("%d\n",Qnum(x,y,w));157 break;158 }159 case 3:{160 x=read();y=read();161 update(x,a[x],y,1,n,1);162 a[x]=y;163 break;164 }165 case 4:{166 x=read();y=read();w=read();167 res=-1e9;168 Qpre(x,y,w,1,n,1);169 printf("%d\n",res);170 break;171 }172 case 5:{173 x=read();y=read();w=read();174 res=1e9;175 Qsub(x,y,w,1,n,1);176 printf("%d\n",res);177 break;178 }179 }180 }181 return 0;182 }
Bzoj3196 Tyvj 1730 二逼平衡树
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。