orz各路神犇,萌新全M,裂开了。
样例过了,题解也用的是递归啊,为啥会M()
#include <queue>
#include <cstdio>
#include <utility>
#include <iostream>
using namespace std;
const int N = 1e4 + 10;
// l表示左儿子,v表示数值,s[i]表示i所在子树的节点个数
int l[N], r[N], v[N], c[N], s[N], idx = 0;
// x是要插入的数,k是节点编号
void add(const int x, int k)
{
s[k]++;
if (v[k] == x) c[k]++;
else if (v[k] < x) // 右子树
{
if (r[k]) add(x, r[k]);
else
{
idx++;
v[idx] = x;
c[idx] = 1;
s[idx] = 1;
r[k] = idx;
}
}
else
{
if (l[k]) add(x, l[k]);
else
{
idx++;
v[idx] = x;
c[idx] = 1;
s[idx] = 1;
l[k] = idx;
}
}
}
// 通过值询问排名
int ask_val(int x, int k)
{
if (v[k] == x) return s[l[k]] + 1; // 不能返回s[k],因为那样会把右子树包括进去
else if (x < v[k]) return ask_val(x, l[k]);
else return s[l[k]] + 1 + ask_val(x, r[k]);
}
int ask_rank(int x, int t, int k)
{
// printf("%d %d %d\n", x, t, k);
if (x == t) return v[k];
else if (x < t) return ask_rank(x, s[l[l[k]]] + 1, l[k]);
else return ask_rank(x, t + s[l[r[k]]] + 1, r[k]);
// s[l[k]] + 1 + s[l[r[k]]] + 1 是错的
}
int main()
{
// 初始化根节点
v[0] = 1e9 + 1;
c[0] = s[0] = 0; // 因为根节点是虚拟节点,所以是0
int m, n = 0;
scanf("%d", &m);
while (m--)
{
int op, x;
scanf("%d %d", &op, &x);
if (op == 1) printf("%d\n", ask_val(x, 1));
else if (op == 2) printf("%d\n", ask_rank(x, n + 1, 0));
else if (op == 3) printf("%d\n", ask_rank(ask_val(x, 1) - 1, n + 1, 0));
else if (op == 4) printf("%d\n", ask_rank(ask_val(x, 1) + 1, n + 1, 0));
else add(x, 0), n++;
c[0] = s[0] = 0;
}
return 0;
}