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