我参考洛谷的书上代码写的(算是半理解半背下来的),但是为什么错了啊。我改了半天最后对照书上好像没有什么不一样的。
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e4 + 9;
int q, root, cnt, op, x;
// 二叉搜索树
struct Node{
int left, right, size, value, num;
//left --> 左子树 right --> 右子树 size --> 表示已该节点的跟节点个数 value --> 权值 num --> 该节点出现的次数
Node(int l, int r, int s, int v)
:left(l), right(r),size(s),value(v),num(1){}
Node(){}
}t[N];
//更新节点信息
inline void update(int root){
// 子树的大小
t[root].size = t[t[root].left].size + t[t[root].right].size + t[root].num;
}
//查找数的排名
int rankk(int x,int root){
if( root ){
//右子树所有的数都比 x 小 所以进左子树
if(x < t[root].value){
return rankk(x, t[root].left);
}
//左子树比 x 小 进入右子树并且加上左子树的大小
if(x > t[root].value){
return rankk(x, t[root].right) + t[t[root].left].size + t[root].num;
return t[t[root].left].size + t[root].num ;
}
return 1;
}
}
//查询排名为 x 的数字
int kth(int x,int root){
//排名为 x 的数在左子树,进入左子树
if(x <= t[t[root].left].size){
return kth(x, t[root].left);
}
//当前根节点就是排名为 x 的数,返回即可
if(x <= t[t[root].left].size + t[root].num){
return t[root].value;
}
//排名为 x 的数在右子树 进入右子树 并且把 x 减去左子树的大小+根节点(t[roor].num)
return kth(x - t[t[root].left].size - t[root].num, t[root].right);
}
//插入值为 x 的数
void insert(int x,int &root){
//插入到左子树
if(x < t[root].value){
//左儿子不存在,新建左节点
if(!t[root].left){
t[t[root].left = ++cnt] = Node(0,0,1,x);
}
//左儿子存在递归插入
else {
insert(x, t[root].left);
}
}
//插入到右子树
else if(x > t[root].value) {
//右儿子不存在,新建右节点
if(!t[root].right){
t[t[root].right = ++ cnt] = Node(0,0,1,x);
}
//右儿子存在递归插入
else {
insert(x, t[root].right);
}
}
// x 的节点已经存在 节点大小加一
else {
t[root].num ++;
}
update(root);
}
int main(){
scanf("%d",&q);
int num_tree = 0;
t[root = ++ cnt] = Node(0,0,1,2147483647);//初始化
while(q--){
scanf("%d%d",&op,&x);
num_tree++;
if(op == 1) printf("%d\n",rankk(x, root));
else if(op == 2) printf("%d\n",kth(x, root));
else if(op == 3) printf("%d\n",kth(rankk(x,root) - 1, root));
else if(op == 4) printf("%d\n",kth(rankk(x + 1, root), root));
else if(op == 5) num_tree-- ,insert(x, root);
}
return 0;
}