题目链接:传送门

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入x数

  2. 删除x数(若有多个相同的数,因只删除一个)

  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

  4. 查询排名为x的数

  5. 求x的前驱(前驱定义为小于x,且最大的数)

  6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( )

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598

Sample Output

106465 84185 492737

Solution

才学Splay,一道Splay的模板题 第一次写200+行的代码,打了2h,调了一天才A掉 看来我还是太弱了。。。 就把板子放这里算了

Code

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

#define root Tree[0].ch[1]
const int Maxn = 100000 + 100;
using namespace std;

struct node
{
int val, ch[2], size, cnt, fa;
}Tree[Maxn];
int M, N;
int points;

inline void update(int x)
{
Tree[x].size = Tree[Tree[x].ch[0]].size + Tree[Tree[x].ch[1]].size + Tree[x].cnt;
return ;
}

inline int judge_dir(int x)
{
return Tree[Tree[x].fa].ch[1] == x;
}

inline void Connect(int x, int f, int dir)
{
Tree[x].fa = f;
Tree[f].ch[dir] = x;
return ;
}

inline void Rotate(int x)
{
int f = Tree[x].fa;
int dirx = judge_dir(x);
int anc = Tree[f].fa;
int dirf = judge_dir(f);
Connect(Tree[x].ch[dirx ^ 1], f, dirx);
Connect(f, x, (dirx ^ 1));
Connect(x, anc, dirf);
update(f); update(x);
return ;
}

inline void Splay (int x, int y)
{
while (Tree[x].fa != y)
{
int f = Tree[x].fa;
int dirx = judge_dir(x), dirf = judge_dir(f);
if (Tree[f].fa == y) Rotate(x);
else if (dirx == dirf) Rotate(f), Rotate(x);
else Rotate(x), Rotate(x);
}
return ;
}

inline int Insert (int x, int f)
{
Tree[++N].val = x;
Tree[N].size = Tree[N].cnt = 1;
Tree[N].fa = f;
return N;
}

inline void Clear(int x)
{
Tree[x].val = 0, Tree[x].fa = 0;
Tree[x].size = 0, Tree[x].cnt = 0;
Tree[x].ch[0] = 0, Tree[x].ch[1] = 0;
return ;
}

inline int Find (int x)
{
int now = root;
while (1)
{
if (Tree[now].val == x)
{
Splay(now, 0);
return now;
}
int dir = (x > Tree[now].val);
if (!Tree[now].ch[dir]) return 0;
now = Tree[now].ch[dir];
}
return 0;
}
inline void Create (int x)
{
points++;
if (!N)
{
root = 1;
Insert(x, 0);
return ;
}
int now = root;
while (1)
{
Tree[now].size ++;
if (Tree[now].val == x)
{
Tree[now].cnt ++;
Splay(now, 0);
return ;
}
int dir = (x > Tree[now].val);
if (!Tree[now].ch[dir])
{
Insert(x, now);
Tree[now].ch[dir] = N;
Splay(N, 0);
return ;
}
now = Tree[now].ch[dir];
}
return ;
}

inline void Delete(int v)
{
int x = Find(v);
if (!x) return ;
points--;
if (Tree[x].cnt > 1)
{
Tree[x].cnt --;
Tree[x].size --;
return ;
}
if (!Tree[x].ch[0])
{
root = Tree[x].ch[1];
Tree[root].fa = 0;
Clear(x);
// cout<<"*"<<root<<endl;
return ;
}
int now = Tree[x].ch[0];
while (Tree[now].ch[1]) now = Tree[now].ch[1];
Splay(now, x);
Connect(Tree[x].ch[1], now, 1);
Connect(now, 0, 1);
// root = now;
update(now);
Clear(x);
return ;
}

inline int Rank(int v)
{
int now = root;
int Ans = 0;
while (1)
{
// cout<<"*"<<now<<endl;
if (Tree[now].val == v) return Ans + Tree[Tree[now].ch[0]].size + 1;
if (now == 0) break;
if (Tree[now].val > v)
now = Tree[now].ch[0];
else Ans += (Tree[Tree[now].ch[0]].size + Tree[now].cnt), now = Tree[now].ch[1];
}
return Ans;
}

inline int Rerank(int x)
{
if (x > points) return -(0x3f3f3f3f);
int now = root;
while (1)
{
int Sum = Tree[now].size - Tree[Tree[now].ch[1]].size;
if (Tree[Tree[now].ch[0]].size < x && x <= Sum)
break;
if (x < Sum)
now = Tree[now].ch[0];
else x -= Sum, now = Tree[now].ch[1];
}
Splay(now, 0);
return Tree[now].val;
}

inline int Pre(int v)
{
int Sum = -(0x3f3f3f3f);
int now = root;
while (1)
{
if (!now) break;
if (Tree[now].val < v && Tree[now].val > Sum) Sum = Tree[now].val;
if (Tree[now].val < v) now = Tree[now].ch[1];
else now = Tree[now].ch[0];
}
return Sum;
}

inline int Next(int v)
{
int Sum = 0x3f3f3f3f;
int now = root;
while (1)
{
if (!now) break;
if (Tree[now].val > v && Tree[now].val < Sum) Sum = Tree[now].val;
if (Tree[now].val > v) now = Tree[now].ch[0];
else now = Tree[now].ch[1];
}
return Sum;
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("A.in", "r", stdin);
freopen("A.out", "w", stdout);
#endif
scanf("%d", &M);
int tot = 0;
while (M --)
{
int op, x;
scanf("%d%d", &op, &x);
if (op == 1) Create(x);
if (op == 2) Delete(x);
if (op == 3) printf("%d\n", Rank(x));
if (op == 4) printf("%d\n", Rerank(x));
if (op == 5) printf("%d\n", Pre(x));
if (op == 6) printf("%d\n", Next(x));
}
return 0;
}