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--;

你可能感兴趣的:(poj)