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 }