首页 > 代码库 > BZOJ3196: Tyvj 1730 二逼平衡树
BZOJ3196: Tyvj 1730 二逼平衡树
3196: Tyvj 1730 二逼平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 775 Solved: 316
[Submit][Status]
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可能为负数
题解:
需要注意几点:
1.一个数的rank是比它小的数的个数+1
2.要使用正确的二分查找
在查找区间第k小的时候,相当于在rank数组中查询k,如果k出现了那么返回k最后出现的位置 否则返回一个位置在这个位置插入k后,rank数组仍然有序
就如上一篇博文中的YES-RIGHT NO-LEFT类型的二分查找
3.求前驱后继的代码要想好怎么写
以pred为例,节点为0时返回-inf,关键值<=节点值则到左子树去寻找,否则到右子树并且判断返回值是否为-inf,
是的话说明右子树为空,而该节点是比关键值小的一个值,没有比它大的了,所以前驱就是该节点
代码:
1 uses math; 2 const maxn=50000+1000;inf=1000000000; 3 type node=record 4 l,r,lch,rch,rt,mid:longint; 5 end; 6 var t:array[0..8*maxn] of node; 7 l,r,s,w,rnd,v,a:array[0..20*maxn] of longint; 8 i,n,m,x,y,z,tot,ch:longint; 9 procedure pushup(k:longint); 10 begin 11 s[k]:=s[l[k]]+s[r[k]]+w[k]; 12 end; 13 procedure rturn(var k:longint); 14 var t:longint; 15 begin 16 t:=l[k];l[k]:=r[t];r[t]:=k;s[t]:=s[k];pushup(k);k:=t; 17 end; 18 procedure lturn(var k:longint); 19 var t:longint; 20 begin 21 t:=r[k];r[k]:=l[t];l[t]:=k;s[t]:=s[k];pushup(k);k:=t; 22 end; 23 procedure ins(var k,num:longint); 24 begin 25 if k=0 then 26 begin 27 inc(tot);k:=tot;v[k]:=num;s[k]:=1;w[k]:=1;l[k]:=0;r[k]:=0; 28 rnd[k]:=random(maxlongint);exit; 29 end; 30 inc(s[k]); 31 if num=v[k] then inc(w[k]) 32 else if num<v[k] then begin ins(l[k],num);if rnd[l[k]]<rnd[k] then rturn(k);end 33 else begin ins(r[k],num);if rnd[r[k]]<rnd[k] then lturn(k);end; 34 end; 35 procedure del(var k,num:longint); 36 begin 37 if v[k]=num then 38 begin 39 if w[k]>1 then begin dec(w[k]);dec(s[k]);exit;end; 40 if l[k]*r[k]=0 then k:=l[k]+r[k] 41 else if rnd[l[k]]<rnd[r[k]] then begin rturn(k);del(k,num);end 42 else begin lturn(k);del(k,num);end; 43 exit; 44 end; 45 dec(s[k]); 46 if num<v[k] then del(l[k],num) else del(r[k],num); 47 end; 48 procedure build(k,x,y:longint); 49 var i:longint; 50 begin 51 with t[k] do 52 begin 53 l:=x;r:=y;mid:=(l+r)>>1; 54 for i:=l to r do ins(rt,a[i]); 55 if l=r then exit; 56 lch:=k<<1;rch:=k<<1+1; 57 build(lch,l,mid);build(rch,mid+1,r); 58 end; 59 end; 60 procedure change(k,x,y:longint); 61 begin 62 with t[k] do 63 begin 64 del(rt,a[x]);ins(rt,y); 65 if l=r then exit; 66 if x<=mid then change(lch,x,y) 67 else change(rch,x,y); 68 end; 69 end; 70 function pred(k,num:longint):longint; 71 begin 72 if k=0 then exit(-inf); 73 if num<=v[k] then pred:=pred(l[k],num) 74 else 75 begin 76 pred:=pred(r[k],num); 77 if pred=-inf then pred:=v[k]; 78 end; 79 end; 80 function succ(k,num:longint):longint; 81 begin 82 if k=0 then exit(inf); 83 if num>=v[k] then succ:=succ(r[k],num) 84 else 85 begin 86 succ:=succ(l[k],num); 87 if succ=inf then succ:=v[k]; 88 end; 89 end; 90 function findpred(k,x,y,z:longint):longint; 91 begin 92 with t[k] do 93 begin 94 if (l=x) and (r=y) then exit(pred(rt,z)); 95 if y<=mid then exit(findpred(lch,x,y,z)) 96 else if x>mid then exit(findpred(rch,x,y,z)) 97 else exit(max(findpred(lch,x,mid,z),findpred(rch,mid+1,y,z))); 98 end; 99 end;100 function findsucc(k,x,y,z:longint):longint;101 begin102 with t[k] do103 begin104 if (l=x) and (r=y) then exit(succ(rt,z));105 if y<=mid then exit(findsucc(lch,x,y,z))106 else if x>mid then exit(findsucc(rch,x,y,z))107 else exit(min(findsucc(lch,x,mid,z),findsucc(rch,mid+1,y,z)));108 end;109 end;110 111 function rank(k,num:longint):longint;112 begin113 if k=0 then exit(0);114 if num=v[k] then exit(s[l[k]])115 else if num<v[k] then exit(rank(l[k],num))116 else exit(s[l[k]]+w[k]+rank(r[k],num));117 end;118 function query(k,x,y,num:longint):longint;119 begin120 with t[k] do121 begin122 if (l=x) and (r=y) then exit(rank(rt,num));123 if y<=mid then exit(query(lch,x,y,num))124 else if x>mid then exit(query(rch,x,y,num))125 else exit(query(lch,x,mid,num)+query(rch,mid+1,y,num));126 end;127 end;128 procedure solverank;129 begin130 readln(x,y,z);131 writeln(query(1,x,y,z)+1);132 end;133 procedure solvefind;134 var l,r,mid:longint;135 begin136 readln(x,y,z);137 l:=0;r:=inf;138 while l<=r do139 begin140 mid:=(l+r)>>1;141 if query(1,x,y,mid)+1>z then r:=mid-1 else l:=mid+1;142 end;143 writeln(r);144 end;145 procedure solvechange;146 begin147 readln(x,y);148 change(1,x,y);149 a[x]:=y;150 end;151 procedure solvepred;152 begin153 readln(x,y,z);154 writeln(findpred(1,x,y,z));155 end;156 procedure solvesucc;157 begin158 readln(x,y,z);159 writeln(findsucc(1,x,y,z));160 end;161 162 procedure init;163 begin164 tot:=0;165 readln(n,m);166 for i:=1 to n do read(a[i]);readln;167 build(1,1,n);168 end;169 procedure main;170 begin171 for i:=1 to m do172 begin173 read(ch);174 case ch of175 1:solverank;176 2:solvefind;177 3:solvechange;178 4:solvepred;179 5:solvesucc;180 end;181 end;182 end;183 begin184 assign(input,‘input.txt‘);assign(output,‘output.txt‘);185 reset(input);rewrite(output);186 init;187 main;188 close(input);close(output);189 end.
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。