蒟蒻代码如下:
#include <cstdio>
#include <iostream>
#define ll long long
#define m10(x) ((x << 3) + (x << 1))
// m10-位优化的*10,只用于快读...
using namespace std;
const ll INF = 2147483647;
const int MAXN = 1e4;
const int s = 1;
// s-根节点
int q, ope, x, tot, lm;
// tot-总值数(含重值); lm-总节点数(不含重值)
struct tree
{
int val, siz, num, fa, ls, rs;
} t[MAXN | 1];
/*
val-值; siz-以该节点为根的树大小(含重值)
num-该节点重值数; fa-父节点
ls、rs-左右子节点
*/
inline int qread()
{
int ot = 0, tmp = getchar();
while (tmp < 48 || tmp > 57)
tmp = getchar();
while (tmp >= 48 && tmp <= 57)
{
ot = m10(ot) + (tmp ^ 48);
tmp = getchar();
}
return ot;
}
// 快读
inline int search(int x)
{
int p = s;
while (t[p].val != x)
if (x < t[p].val)
p = t[p].ls;
else
p = t[p].rs;
return p;
}
// 查询值为x的节点编号
inline int find(int x)
{
int p = s, ot = 1;
while (t[p].val != x)
{
if (x < t[p].val)
p = t[p].ls;
else
{
ot += t[t[p].ls].siz + t[p].num;
p = t[p].rs;
}
}
ot += t[t[p].ls].siz;
return ot;
}
//查询小于x的值个数
inline int ask(int x)
{
int p = s;
while (x < t[t[p].ls].siz + 1 || x > t[t[p].ls].siz + t[p].num)
{
if (x < t[t[p].ls].siz + 1)
p = t[p].ls;
else
{
x -= t[t[p].ls].siz + t[p].num;
p = t[p].rs;
}
}
return t[p].val;
}
// 查询第x小的值
inline ll lst(int x)
{
int p = find(x);
if (!(p ^ 1)) // 若x为第一个值
return -1 * INF;
int k = ask(p - 1);
return k;
}
// 查询x的前驱
inline ll nxt(int x)
{
int p = find(x);
int tmp = search(x);
if (p + t[tmp].num > tot)
return INF;
int k = ask(p + t[tmp].num);
return k;
}
// 查询x的后驱
inline void ins(int x)
{
int p = s;
while (1)
{
++t[p].siz; // x一定是p或其子节点的值
if (t[p].val == x)
{
++t[p].num;
return;
}
if (x > t[p].val)
{
if (!t[p].rs)
{
t[++lm].val = x;
t[lm].num = 1;
t[lm].siz = 1;
t[lm].fa = p;
t[p].rs = lm;
return;
}
p = t[p].rs;
}
else
{
if (!t[p].ls)
{
t[++lm].val = x;
t[lm].num = 1;
t[lm].siz = 1;
t[lm].fa = p;
t[p].ls = lm;
return;
}
p = t[p].ls;
}
}
}
// 插入x
int main()
{
q = qread();
while (q--)
{
ope = qread();
x = qread();
switch (ope) // switch整整齐齐(
{
case 1:
printf("%d\n", find(x));
break;
case 2:
printf("%d\n", ask(x));
break;
case 3:
printf("%lld\n", lst(x));
break;
case 4:
printf("%lld\n", nxt(x));
break;
case 5:
++tot;
if (!lm) // 若为插入的第一个值
{
t[++lm].val = x;
t[lm].siz = 1;
t[lm].num = 1;
}
else
ins(x);
}
}
return 0;
}