poj2182 Lost Cows

 1 #include<stdio.h>
 2 #define N 8010
 3 struct node{
 4     int l,r;
 5     int len;//len用来存放某一段数据的个数 
 6 }tree[N<<1];
 7 int s[N],result[N];
 8 void build(int l,int r,int i)
 9 {
10     tree[i].l=l;
11     tree[i].r=r;
12     tree[i].len=r-l+1; 
13     if(l==r) return;
14     int mid=(l+r)>>1;
15     build(l,mid,i<<1);
16     build(mid+1,r,(i<<1)+1);
17 }
18 int order(int s,int i)
19 {
20     tree[i].len--;//每进行一次取出操作,结点个数都要减一 
21     if(tree[i].l==tree[i].r) return tree[i].l;//树的l就是牛的编号 
22     if(s<=tree[i<<1].len) return order(s,i<<1);//假如要找的第s名的s<左子树的左边界,则在左子树上查找 
23     else return order(s-tree[i<<1].len,(i<<1)+1);//否则在右子树上查找,注意在右子树查找时,是查找第(s-tree[i<<1])个节点的编号 
24 }
25 int main()
26 {
27     int i,n;
28     while(~scanf("%d",&n)){
29         build(1,n,1);
30         for(i=1;i<n;++i)
31             scanf("%d",&s[i]);
32         for(i=n-1;i>0;--i)
33             result[i]=order(s[i]+1,1);
34         result[0]=order(1,1);//最后一个就剩一个了,也就是第一个 
35         for(i=0;i<n;++i)
36             printf("%d\n",result[i]);
37     }
38     return 0;
39 }

搜索排在第n位的数是几时可用线段树实现,对于一个线段树中的所代表的线段[a,b],结点中的数值纪录[a,b]中有多少人,记为len,所以对于一个在剩余数字队列中排在第n位,看这个人是在一个结点的左子树中还是右子树中,

判断的依据是用左子树的r和n比较,

如果r>=n说明在左子树形成的队列中有足够的数字使他排在第n位,于是递归找左子树。

如果r <n说明在左子树形成的队列中没有足够的数字使他排在第n位,所以他在右子树的第n-r位,于是递归在右子树中找;

当然每找到一个数字,要将所有的祖先结点信息改变,即len--;

原文地址:https://www.cnblogs.com/shihuajie/p/2631908.html