[代码] bzoj 3224 普通平衡树(无旋treap)
- 传送门 -
http://www.lydsy.com/JudgeOnline/problem.php?id=3224
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 17311 Solved: 7553
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
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
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
- 代码 -
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <ctime>
#include <cstdlib>
#define pii pair<int, int>
#define mp make_pair
using namespace std;
template <typename ty> void read(ty &x) {
x = 0; int f = 1; char ch = getchar();
while (ch > '9' || ch < '0') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x*10 + ch - '0'; ch = getchar(); }
x *= f;
}
template <typename ty> ty Max(ty a, ty b) { return a > b ? a : b; }
template <typename ty> ty Min(ty a, ty b) { return a < b ? a : b; }
template <typename ty> int Chkmin(ty a, ty b) { return a > b ? a = b, 1 : 0; }
template <typename ty> int Chkmax(ty a, ty b) { return a < b ? a = b, 1 : 0; }
typedef long long LL;
typedef double db;
const int inf = 0x7fffffff;
const int N = 1e5 + 16;
int V[N], C[N][2], SZ[N], RD[N];
int n, sz, tot, root;
void pushup(int rt) { SZ[rt] = SZ[C[rt][0]] + SZ[C[rt][1]] + 1; }
int build(int val) {
sz++;
V[sz] = val;
RD[sz] = rand();
SZ[sz] = 1;
return sz;
}
pii split(int rt, int k) {
if (!rt) return mp(0, 0);
pii tmp;
if (SZ[C[rt][0]] >= k) {
tmp = split(C[rt][0], k); C[rt][0] = tmp.second;
pushup(rt); tmp.second = rt;
}
else {
tmp = split(C[rt][1], k - SZ[C[rt][0]] - 1); C[rt][1] = tmp.first;
pushup(rt); tmp.first = rt;
}
return tmp;
}
int merge(int ra, int rb) {
if (!ra) return rb;
if (!rb) return ra;
if (RD[ra] < RD[rb]) {
C[ra][1] = merge(C[ra][1], rb);
pushup(ra); return ra;
}
else {
C[rb][0] = merge(ra, C[rb][0]);
pushup(rb); return rb;
}
}
int getkth(int rt, int val) {
if (!rt) return 0;
if (V[rt] >= val) return getkth(C[rt][0], val);
return SZ[C[rt][0]] + 1 + getkth(C[rt][1], val);
}
int findkth(int rt, int k) {
pii a = split(root, k - 1);
pii b = split(a.second, 1);
int ans = b.first;
root = merge(merge(a.first, ans), b.second);
return ans;
}
void work1(int v) {
int tmp = getkth(root, v);
pii a = split(root, tmp);
root = merge(merge(a.first, build(v)), a.second);
}
void work2(int v) {
int tmp = getkth(root, v);
int t = findkth(root, tmp + 1);
if (!t || V[t] != v) return;
pii a = split(root, tmp);
pii b = split(a.second, 1);
root = merge(a.first, b.second);
}
void work3(int v) { printf("%d\n", getkth(root, v) + 1); }
void work4(int v) { printf("%d\n", V[findkth(root, v)]); }
void work5(int v) { printf("%d\n", V[findkth(root, getkth(root, v))]); }
void work6(int v) { printf("%d\n", V[findkth(root, getkth(root, v + 1) + 1)]); }
int main () {
read(n);
while (n --) {
int opt, v;
read(opt); read(v);
switch(opt) {
case 1: { work1(v); break; }
case 2: { work2(v); break; }
case 3: { work3(v); break; }
case 4: { work4(v); break; }
case 5: { work5(v); break; }
case 6: { work6(v); break; }
}
}
return 0;
}