# bzoj3224

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;
181   for i:=1 to n do
182   begin
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  阅读(182)  评论(0编辑  收藏  举报