随笔 - 540  文章 - 0 评论 - 39 阅读 - 12万
< 2025年1月 >
29 30 31 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 1
2 3 4 5 6 7 8

平衡树模板在此!
写了treap(话说好久没写splay了)
注意对相同元素的处理

UPD:其实这里处理的不好,每个点可以代表一个元素值,然后记录出现次数即可,不用新添一个点

复制代码
  1 const rd=200007;
  2 var fa,key,a,count:array[0..200010] of longint;
  3     son:array[0..200010,1..2] of longint;
  4     t,root,ch,x,i,n:longint;
  5 
  6 procedure clear(x:longint);
  7   begin
  8     son[x,1]:=0;
  9     son[x,2]:=0;
 10     fa[x]:=0;
 11     count[x]:=1;
 12     fa[0]:=-1;
 13     count[0]:=0;
 14   end;
 15 
 16 procedure update(x:longint);
 17   begin
 18     count[x]:=count[son[x,1]]+count[son[x,2]]+1;
 19   end;
 20 
 21 procedure rotate(x,w:longint);
 22   var y:longint;
 23   begin
 24     y:=fa[x];
 25     if fa[y]<>0 then
 26     begin
 27       if son[fa[y],1]=y then son[fa[y],1]:=x
 28       else son[fa[y],2]:=x;
 29     end
 30     else root:=x;
 31     fa[x]:=fa[y];
 32     son[y,3-w]:=son[x,w];
 33     fa[son[x,w]]:=y;
 34     son[x,w]:=y;
 35     fa[y]:=x;
 36     update(y);
 37     update(x);
 38   end;
 39 
 40 procedure up(i:longint);
 41   var j:longint;
 42   begin
 43     j:=fa[i];
 44     while (j<>0) and (key[j]>key[i]) do
 45     begin
 46       if son[j,1]=i then rotate(i,2)
 47       else rotate(i,1);
 48       j:=fa[i];
 49     end;
 50   end;
 51 
 52 procedure sift(i:longint);
 53   var j1,j2:longint;
 54   begin
 55     repeat
 56       j1:=son[i,1];
 57       j2:=son[i,2];
 58       if (j1=0) and (j2=0) then break;
 59       if (j1=0) then
 60         rotate(j2,1)
 61       else if j2=0 then
 62         rotate(j1,2)
 63       else begin
 64         if (key[j1]>key[j2]) then
 65           rotate(j2,1)
 66         else rotate(j1,2);
 67       end;
 68     until false;
 69   end;
 70 
 71 function find(x:longint):longint;
 72   var p:longint;
 73   begin
 74     p:=root;
 75     while true do
 76     begin
 77       if a[p]=x then exit(p);
 78       if a[p]>x then p:=son[p,1]
 79       else p:=son[p,2];
 80     end;
 81   end;
 82 
 83 procedure insert(x:longint);
 84   var p:longint;
 85   begin
 86     inc(t);
 87     key[t]:=trunc(random*rd)+1;
 88     a[t]:=x;
 89     clear(t);
 90     if root=0 then root:=t
 91     else begin
 92       p:=root;
 93       repeat
 94         inc(count[p]);
 95         if a[p]>x then
 96         begin
 97           if son[p,1]=0 then break;
 98           p:=son[p,1];
 99         end
100         else begin
101           if son[p,2]=0 then break;
102           p:=son[p,2];
103         end;
104       until false;
105       fa[t]:=p;
106       if a[p]>x then son[p,1]:=t else son[p,2]:=t;
107       up(t);
108     end;
109   end;
110 
111 procedure delete(x:longint);
112   var i,p:longint;
113   begin
114     i:=find(x);
115     sift(i);
116     if fa[i]=0 then root:=0;
117     p:=fa[i];
118     while p<>0 do
119     begin
120       dec(count[p]);
121       p:=fa[p];
122     end;
123     if son[fa[i],1]=i then son[fa[i],1]:=0
124     else son[fa[i],2]:=0;
125     clear(i);
126   end;
127 
128 function kth(x:longint):longint;
129   var p:longint;
130   begin
131     p:=root;
132     while true do
133     begin
134       if count[son[p,1]]+1=x then exit(a[p]);
135       if count[son[p,1]]+1>x then p:=son[p,1]
136       else begin
137         x:=x-count[son[p,1]]-1;
138         p:=son[p,2];
139       end;
140     end;
141   end;
142 
143 function rank(x:longint):longint;
144   var p:longint;
145   begin
146     p:=root;
147     rank:=1;
148     while p<>0 do
149     begin
150       if a[p]>=x then p:=son[p,1]  //注意这里的等号,因为是要找最小的排名
151       else begin
152         rank:=rank+count[son[p,1]]+1;
153         p:=son[p,2];
154       end;
155     end;
156   end;
157 
158 function pre(p,x:longint):longint;
159   begin
160     if p=0 then exit(-1);
161     if a[p]>=x then exit(pre(son[p,1],x))
162     else begin
163       pre:=pre(son[p,2],x);
164       if pre=-1 then pre:=a[p];
165     end;
166   end;
167 
168 function succ(p,x:longint):longint;
169   begin
170     if p=0 then exit(-1);
171     if a[p]<=x then exit(succ(son[p,2],x))
172     else begin
173       succ:=succ(son[p,1],x);
174       if succ=-1 then succ:=a[p];
175     end;
176   end;
177 
178 begin
179   randomize;
180   readln(n);
181   for i:=1 to n do
182   begin
183     readln(ch,x);
184     if ch=1 then
185       insert(x)
186     else if ch=2 then
187       delete(x)
188     else if ch=3 then
189       writeln(rank(x))
190     else if ch=4 then
191       writeln(kth(x))
192     else if ch=5 then
193       writeln(pre(root,x))
194     else writeln(succ(root,x));
195   end;
196 end.
View Code
复制代码

 

posted on   acphile  阅读(185)  评论(0编辑  收藏  举报
编辑推荐:
· 你所不知道的 C/C++ 宏知识
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· SQL Server 内存占用高分析
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
阅读排行:
· 我干了两个月的大项目,开源了!
· 推荐一款非常好用的在线 SSH 管理工具
· 千万级的大表,如何做性能调优?
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· .NET周刊【1月第1期 2025-01-05】
点击右上角即可分享
微信分享提示