平衡树模板在此!
写了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 2014-11-07 15:16  acphile  阅读(180)  评论(0编辑  收藏  举报