rt, link
样例过不了:
输入:
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
我的输出:
106465
106465
492737
应该的输出:
106465
84185
492737
我的代码:
#include <iostream>
#include <cstdio>
#include <random>
#include <time.h>
using namespace std ;
namespace OIfast {
typedef long long lint ;
typedef long double dint ;
// 快读
void read(lint &x) {
char c ; bool b = true ;
for (c = getchar() ; !isdigit(c) ; c = getchar())
if (c == '-') b = false ;
for (x = 0 ; isdigit(c) ; c = getchar())
x = x * 10 + c - '0' ;
if (b == false) x *= -1 ;
return ;
}
// 快写
void write(lint x) {
if (x < 0) putchar('-'), x *= -1 ;
if (x >= 10) write(x / 10) ;
putchar(x % 10 + '0') ;
return ;
}
// 快写组件
void writer(lint x, char c) {
write(x) ;
putchar(c) ;
return ;
}
}
namespace FHQ_Treap {
typedef long long lint ;
typedef long double dint ;
struct Node {
lint Size ;
lint val, rnd ;
lint Left, Right ;
};
lint root, idx ;
vector<Node> tree ;
// 创建新的节点
lint get_Node(lint val) {
idx ++ ;
tree[idx].Size = 1 ;
tree[idx].val = val ;
tree[idx].rnd = rand() ;
return idx ;
}
// 向上更新父节点
void push_up(lint x) {
Node &Now = tree[x] ;
const Node &Leftson = tree[tree[x].Left] ;
const Node &Rightson = tree[tree[x].Right] ;
Now.Size = Leftson.Size + Rightson.Size + 1 ;
}
// 权值分裂: 当前在节点 now,将树分裂成以 x 为根(权值全部小于等于 k)、以 y 为根(权值全部大于 k)的两颗树
void split(lint now, lint k, lint &x, lint &y) {
if (!now) {x = y = 0 ; return ;}
if (tree[now].val <= k) {
x = now ;
split(tree[now].Right, k, tree[now].Right, y) ;
} else {
y = now ;
split(tree[now].Left, k, x, tree[now].Left) ;
}
push_up(now) ;
return ;
}
// 排名分裂: 当前在节点 now,将树分裂成以 x 为根(权值全部小于等于 k)、以 y 为根(权值全部大于 k)的两颗树
void division(lint now, lint k, lint &x, lint &y) {
if (!now) {x = y = 0 ; return ;}
if (k < tree[tree[now].Left].Size) {
y = now ;
lint son = tree[now].Left ;
division(son, k, x, son) ;
} else {
x = now ;
lint son = tree[now].Right ;
division(son, k - tree[tree[now].Left].Size - 1, son, y) ;
}
push_up(now) ;
return ;
}
// 合并: 合并以 x 为根和以 y 为根的两颗树(x 所有点的权值都小于 y 所有点的权值)
lint merge(lint x, lint y) {
if (!x || !y) return x | y ;
if (tree[x].rnd < tree[y].rnd) {
tree[x].Right = merge(tree[x].Right, y) ;
push_up(x) ;
return x ;
} else {
tree[x].Left = merge(x, tree[x].Left) ;
push_up(y) ;
return y ;
}
}
// 插入: 插入权值为 val 的点
void insert(lint val) {
lint x, y ;
split(root, val, x, y) ;
root = merge(merge(x, get_Node(val)), y) ;
return ;
}
// 区间删除: 删除给定权值为 val 的所有点
void remove(lint val) {
lint x, y, z ;
split(root, val, x, z) ;
split(x, val - 1, x, y) ;
root = merge(x, z) ;
}
// 单点删除: 删除给定权值为 val 的其中一个点
void Delete(lint val) {
lint x, y, z ;
split(root, val, x, z) ;
split(x, val - 1, x, y) ;
if (y) y = merge(tree[y].Left, tree[y].Right) ;
root = merge(merge(x, y), z) ;
return ;
}
// 求第 k 小的数
lint kth(lint root, lint k) {
lint now = root ;
while (true) {
if (k <= tree[tree[now].Left].Size) now = tree[now].Left ;
else if (k == tree[tree[now].Left].Size + 1) return tree[now].val ;
else {
k -= tree[tree[now].Left].Size + 1 ;
now = tree[now].Right ;
}
}
return -1 ;
}
// 查询权值为 val 的节点的排名
lint Rank(lint val) {
lint x, y ;
split(root, val - 1, x, y) ;
lint res = tree[x].Size + 1 ;
root = merge(x, y) ;
return res ;
}
// 查询权值为 val 的节点的前驱
lint Predecessor(lint val) {
lint x, y ;
split(root, val - 1, x, y) ;
lint res = kth(x, tree[x].Size) ;
root = merge(x, y) ;
return res ;
}
// 查询权值为 val 的节点的后继
lint Successor(lint val) {
lint x, y ;
split(root, val, x, y) ;
lint res = kth(y, 1) ;
root = merge(x, y) ;
return res ;
}
}
using namespace OIfast ;
using namespace FHQ_Treap ;
const lint MAXN = 1e5 + 5 ;
const lint INF = 0x7fffffff ;
lint n ;
lint opt, a ;
signed main ( ) {
read(n) ;
// srand(time(NULL)) ;
tree.resize(MAXN, Node()) ;
for (lint i = 1 ; i <= n ; i ++) {
read(opt), read(a) ;
if (opt == 0) puts("Error !!!") ;
else if (opt == 1) insert(a) ;
else if (opt == 2) Delete(a) ;
else if (opt == 3) insert(a), writer(Rank(a), '\n'), Delete(a) ;
else if (opt == 4) writer(kth(root, a), '\n') ;
else if (opt == 5) writer(Predecessor(a), '\n') ;
else if (opt == 6) writer(Successor(a), '\n') ;
}
return 0 ;
}