您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
第一行为 n n n,表示操作的个数,下面 n n n 行每行有两个数 opt \text{opt} opt 和 x x x, opt \text{opt} opt 表示操作的序号( $ 1 \leq \text{opt} \leq 6 $ )
对于操作 3 , 4 , 5 , 6 3,4,5,6 3,4,5,6 每行输出一个数,表示对应答案
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
106465
84185
492737
【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 5 1\le n \le 10^5 1≤n≤105, ∣ x ∣ ≤ 1 0 7 |x| \le 10^7 ∣x∣≤107
来源:Tyvj1728 原名:普通平衡树
在此鸣谢
#include
#define LL long long
#define PP pair <int, int>
using namespace std;
const int N = 1e5 + 10;
struct Treap {
int l, r, val, pri, num, size;//左右子节点,值,优先级,重复个数,跟的子树大小
} tree[N];
int T, cnt;
int root;
inline int read () {
int s = 0, f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') {
if (ch == '-')
f = -1;
ch = getchar ();
}
while (ch >= '0' && ch <= '9') {
s = (s << 1) + (s << 3) + (ch ^ '0');
ch = getchar ();
}
return s * f;
}
void write (int x) {
if (x < 0) {
putchar ('-');
x = -x;
}
if (x > 9)
write (x / 10);
putchar (x % 10 + '0');
}
inline int New (int val) {//生成新节点
tree[ ++ cnt].val = val;//点权
tree[cnt].pri = rand ();//给一个随机数作为优先级
tree[cnt].num = tree[cnt].size = 1;//子树大小和重复个数均为1
tree[cnt].l = tree[cnt].r = 0;//没有左右节点
return cnt;
}
inline void Update (int p) {//更新子树大小
tree[p].size = tree[tree[p].l].size + tree[tree[p].r].size + tree[p].num;//当前子树的大小为左子树的大小加右子树大小叫重复的个数
}
inline void zig (int &p) {//右旋
int q = tree[p].l;
tree[p].l = tree[q].r;
tree[q].r = p;
tree[q].size = tree[p].size;
Update (p);
p = q;
}
inline void zag (int &p) {//左旋
int q = tree[p].r;
tree[p].r = tree[q].l;
tree[q].l = p;
tree[q].size = tree[p].size;
Update (p);
p = q;
}
void Insert (int &p, int val) {//在p的子树中插入val
if (!p) {//如果没有,则新建一个
p = New (val);
return;
}
tree[p].size ++ ;
if (val == tree[p].val) {
tree[p].num ++ ;
return;
}
if (val < tree[p].val) {
Insert (tree[p].l, val);
if (tree[p].pri < tree[tree[p].l].pri) zig (p);
}
if (val > tree[p].val) {
Insert (tree[p].r, val);
if (tree[p].pri < tree[tree[p].r].pri) zag (p);
}
}
void Delete (int &p, int val) {//在p的子树中删除val
if (!p) return;
tree[p].size -- ;
if (val == tree[p].val) {
if (tree[p].num > 1) {
tree[p].num -- ;
return;
}
if (!tree[p].l || !tree[p].r)
p = tree[p].l + tree[p].r;
else if (tree[tree[p].l].pri > tree[tree[p].r].pri) {
zig (p);
Delete (tree[p].r, val);
}
else {
zag (p);
Delete (tree[p].l, val);
}
return;
}
if (val < tree[p].val) Delete (tree[p].l, val);
if (val > tree[p].val) Delete (tree[p].r, val);
}
inline int Getpre (int val) {//找前驱
int p = root;
int res = 0;
while (p) {
if (tree[p].val < val) {
res = tree[p].val;
p = tree[p].r;
}
else p = tree[p].l;
}
return res;
}
inline int Getnext (int val) {//找后继
int p = root;
int res = 0;
while (p) {
if (tree[p].val > val) {
res = tree[p].val;
p = tree[p].l;
}
else p = tree[p].r;
}
return res;
}
int getRanking (int p, int val) {//根据val查找排名
if (!p) return 0;
if (tree[p].val == val) return tree[tree[p].l].size + 1;
if (val < tree[p].val) return getRanking (tree[p].l, val);
if (val > tree[p].val) return getRanking (tree[p].r, val) + tree[tree[p].l].size + tree[p].num;
}
int UseRankingfindval (int p, int rank) {//根据排名rank查找val
if (!p) return 0;
if (tree[tree[p].l].size >= rank) return UseRankingfindval (tree[p].l, rank);
if (tree[tree[p].l].size + tree[p].num >= rank) return tree[p].val;
return UseRankingfindval (tree[p].r, rank - tree[tree[p].l].size - tree[p].num);
}
int main () {
T = read ();
register int op, x;
while (T -- ) {
op = read (), x = read ();
if (op == 1) Insert (root, x);
if (op == 2) Delete (root, x);
if (op == 3) write (getRanking (root, x)), puts ("");
if (op == 4) write (UseRankingfindval (root, x)), puts ("");
if (op == 5) write (Getpre (x)), puts ("");
if (op == 6) write (Getnext (x)), puts ("");
}
return 0;
}