1 #include<bits/stdc++.h>
2 using namespace std;
3 const int MAXN=1024;
4 struct node{
5 int val; // val:该节点储存的数值
6 int lch, rch; // lch: 左子树根节点编号,rch:右子树根节点编号
7 int cnt; //该节点储存的数出现的次数(由于我们这里维护的是可重集)
8 int sz; //以该节点为根节点的子树的节点数目(即子树大小)
9 };
10 node bst[MAXN];
11 int id=1;
12 //插入
13 void insert(int v, int pos=1)//插入
14 {
15 bst[pos].sz++;// 以该节点为根节点的子树大小+1
16 if(bst[pos].val==0 && bst[pos].lch==0 && bst[pos].rch==0){//空节点
17 bst[pos].val=v;
18 bst[pos].cnt=1;
19 }
20 else if(v<bst[pos].val){// 向左搜索
21 if(bst[pos].lch==0)// 如果应该向左搜,但不存在左节点,则创建一个新节点
22 bst[pos].lch=++id;
23 insert(v, bst[pos].lch);
24 }
25 else if(v>bst[pos].val){// 向右搜索
26 if(bst[pos].rch==0)
27 bst[pos].rch=++id;
28 insert(v, bst[pos].rch);
29 }
30 else//已经存在相同值的点
31 bst[pos].cnt++;
32 }
33 //删除
34 void remove(int v, int pos=1){
35 bst[pos].sz--;
36 if(v<bst[pos].val)
37 remove(v, bst[pos].lch);
38 else if(v>bst[pos].val)
39 remove(v, bst[pos].rch);
40 else
41 bst[pos].cnt--;
42 }
43 //求排名:因为排名被定义为比某数小的数+1,所以我们直接实现两个函数countl和countg,
44 //用来求比某数小的数的数量和比某数大的数的数量。(这两个函数后面也会用到)
45 int countl(int v, int pos=1){// 求比某数小的数的个数
46 if(v<bst[pos].val)
47 return bst[pos].lch?countl(v, bst[pos].lch):0;
48 else if(v>bst[pos].val)
49 return bst[bst[pos].lch].sz+bst[pos].cnt+bst[pos].rch?countl(v, bst[pos].rch):0;
50 else
51 return bst[bst[pos].lch].sz;
52 }
53 int countg(int v, int pos=1){// 求比某数大的数的个数
54 if(v>bst[pos].val)
55 return bst[pos].rch?countg(v, bst[pos].rch):0;
56 else if(v<bst[pos].val)
57 return bst[bst[pos].rch].sz+bst[pos].cnt+bst[pos].lch?countg(v, bst[pos].lch):0;
58 else
59 return bst[bst[pos].rch].sz;
60 }
61 //查询某值在数列中排名
62 int rank(int v){
63 return countl(v, 1)+1;
64 }
65 //求指定排名的数
66 int kth(int k, int pos=1)// 求指定排名的数
67 {
68 if(bst[bst[pos].lch].sz+1>k)// 答案在左,在左子树中找排名为k的数
69 return kth(k, bst[pos].lch);
70 else if(bst[bst[pos].lch].sz+bst[pos].cnt<k)// 答案在右,在右子树中找排名为k - size[L[pos]] - N[pos]的数
71 return kth(k-bst[bst[pos].lch].sz-bst[pos].cnt, bst[pos].rch);
72 else
73 return bst[pos].val;
74 }
75 //注意,假如某个数的排名为2,且它出现了3次,那么这个函数传入2、3、4都会返回这个数,这也提供了一些方便。
76
77
78 //求前驱:根据我们kth函数的性质,直接找到排名比当前数小1的那个数即可。
79 int pre(int v){
80 int r=countl(v);
81 return kth(r);
82 }
83
84 //求后继:后继的排名则是小于等于当前数的数的数量+1。
85 int suc(int v){
86 int r = bst[1].sz - countg(v) + 1;
87 return kth(r);
88 }
89 int main()
90 {
91 //依次插入 10 6 2 5 1 7 4 2 5 9 5
92 int n;
93 cin>>n;
94 for(int i=0; i<n; i++){
95 int x;
96 cin>>x;
97 insert(x);
98 }
99 for(int i=1; i<=id; i++)
100 cout<<i<<":"<<bst[i].val<<" "<<bst[i].lch<<" "<<bst[i].rch<<" "<<bst[i].sz<<" "<<bst[i].cnt<<endl;
101 cout<<rank(6)<<endl;
102 return 0;
103 }