普通平衡树
/*您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1 插入 x 数
2 删除 x数(若有多个相同的数,因只删除一个)
3 查询 x 数的排名(排名定义为比当前数小的数的个数 +1 )
4 查询排名为 x 的数
5 求 x 的前驱(前驱定义为小于 x,且最大的数)
6 求 x 的后继(后继定义为大于 x,且最小的数)
7 输入格式
*/
//#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <climits>
#include <queue>
#include <vector>
#include <stack>
#include <algorithm>
#include <cctype>
#define FAST_IO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define mem(a, b) memset(a,b,sizeof(a))
#define int long long
#define rint register int
using namespace std;
template<class T>
void tomax(T &a, T b) { a = max(a, b); }
template<class T>
void tomin(T &a, T b) { a = min(a, b); }
typedef long long ll;
typedef pair<int, int> pii;
// #define DEBUG 1
struct IO {
#define MAXSIZE (1 << 20)
#define isdigit(x) (x >= '0' && x <= '9')
char buf[MAXSIZE], *p1, *p2;
char pbuf[MAXSIZE], *pp;
#if DEBUG
#else
IO() : p1(buf), p2(buf), pp(pbuf) {}
~IO() { fwrite(pbuf, 1, pp - pbuf, stdout); }
#endif
inline char gc() {
#if DEBUG
return getchar();
#endif
if (p1 == p2) p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin);
return p1 == p2 ? ' ' : *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
template<class T>
inline void read(T &x) {
register double tmp = 1;
register bool sign = 0;
x = 0;
register char ch = gc();
for (; !isdigit(ch); ch = gc())
if (ch == '-') sign = 1;
for (; isdigit(ch); ch = gc()) x = x * 10 + (ch - '0');
if (ch == '.')
for (ch = gc(); isdigit(ch); ch = gc())
tmp /= 10.0, x += tmp * (ch - '0');
if (sign) x = -x;
}
inline void read(char *s) {
register char ch = gc();
for (; blank(ch); ch = gc());
for (; !blank(ch); ch = gc()) *s++ = ch;
*s = 0;
}
inline void read(char &c) {
for (c = gc(); blank(c); c = gc());
}
inline void push(const char &c) {
#if DEBUG
putchar(c);
#else
if (pp - pbuf == MAXSIZE) fwrite(pbuf, 1, MAXSIZE, stdout), pp = pbuf;
*pp++ = c;
#endif
}
template<class T>
inline void write(T x) {
if (x < 0) x = -x, push('-'); // 负数输出
static T sta[35];
T top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
while (top) push(sta[--top] + '0');
}
template<class T>
inline void write(T x, char lastChar) {
write(x), push(lastChar);
}
} io;
using namespace std;
#define int long long
#define FAST_IO
const int MAXN = 1e5 + 10;
struct offline {
int q, x;
} offline[MAXN];
struct Node {
int l, r, val;
} T[MAXN << 2];
int b[MAXN];
int nums;
void build(int root, int l, int r) {
T[root].l = l, T[root].r = r, T[root].val = 0;
if (l == r)return;
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
}
void pushup(int root) {
T[root].val = T[root << 1].val + T[root << 1 | 1].val;
}
//$param: 根节点 要更新的数字 要更新的权值
//
void update(int root, int x, int q) {
if (T[root].l == T[root].r) {
T[root].val += q;
return;
}
int mid = (T[root].l + T[root].r) >> 1;
if (x <= mid)update(root << 1, x, q);
else update(root << 1 | 1, x, q);
pushup(root);
}
int query(int root, int l, int r) {
int ans = 0;
if (T[root].l >= l && T[root].r <= r)return T[root].val;
int mid = (T[root].l + T[root].r) >> 1;
if (l <= mid)ans += query(root << 1, l, r);
if (r > mid) return ans += query(root << 1 | 1, l, r);
return ans;
}
int dequery(int root, int len) {
if (T[root].l == T[root].r)return T[root].l;
if (T[root << 1].val >= len)dequery(root << 1, len);
else return dequery(root << 1 | 1, len - T[root << 1].val);
}
signed main() {
int n;
io.read(n);
build(1, 1, 1e5);
for (int i = 1; i <= n; i++) {
io.read(offline[i].q), io.read(offline[i].x);
if (offline[i].q != 4) {
b[++nums] = offline[i].x;
}
}
sort(b + 1, b + 1 + nums);
//返回最后一个数的下表
nums = unique(b + 1, b + 1 + nums) - (b + 1);
for (int i = 1; i <= n; i++) {
int x = offline[i].x;
if (offline[i].q != 4) {
x = lower_bound(b + 1, b + 1 + nums, x) - b;
}
int ans;
switch (offline[i].q) {
//特定数字权值加一
case 1:
update(1, x, 1);
break;//特定数字权值减一
case 2:
update(1, x, -1);
break;
//查询x的排名
case 3:
ans = query(1, 1, x - 1);
ans++;
io.write(ans, '\n');
break;
//查询排在第k位的是什么数字
case 4:
ans = dequery(1, x);
io.write(b[ans], '\n');
break;
//查询x的前驱数字,先查询x-1的排位,
case 5:
ans = query(1, 1, x - 1);
io.write(b[dequery(1, ans)], '\n');
break;
//查询x的后继数字,先查询x的
case 6:
ans = query(1, 1, x);
io.write(b[dequery(1, ans + 1)], '\n');
break;
}
}
return 0;
}