Lost Cows

Lost Cows

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 4   Accepted Submission(s) : 2
Problem Description
N (2 <= N <= 8,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood 'watering hole' and drank a few too many beers before dinner. When it was time to line up for their evening meal, they did not line up in the required ascending numerical order of their brands. 
Regrettably, FJ does not have a way to sort them. Furthermore, he's not very good at observing problems. Instead of writing down each cow's brand, he determined a rather silly statistic: For each cow in line, he knows the number of cows that precede that cow in line that do, in fact, have smaller brands than that cow. 
Given this data, tell FJ the exact ordering of the cows. 
 

 

Input
* Line 1: A single integer, N 
* Lines 2..N: These N-1 lines describe the number of cows that precede a given cow in line and have brands smaller than that cow. Of course, no cows precede the first cow in line, so she is not listed. Line 2 of the input describes the number of preceding cows whose brands are smaller than the cow in slot #2; line 3 describes the number of preceding cows whose brands are smaller than the cow in slot #3; and so on. 
 

 

Output
* Lines 1..N: Each of the N lines of output tells the brand of a cow in line. Line #1 of the output tells the brand of the first cow in line; line 2 tells the brand of the second cow; and so on.
 

 

Sample Input
5
1
2
1
0
 

 

Sample Output
2
4
5
3
1
 

 

Source
PKU
 
题目大意:有N头牛,没有头牛都有各自的编号,分别是从1~N,现在牛随机排成一排,只知道第i头牛的左边有多少头比它编号小的牛的数量。
第一行,输入N,表示有N头牛,分别是编号从1~N。接下去有N-1行,表示从第2位置开始到最后一个位置的,分别表示第i位置的牛左边有多少编号比它小的牛。我们从右边推,如果知道最右边的牛在它左边编号比它小的牛有n头,我们就可以知道,这头牛的编号肯定是第n+1小的,然后把这个编号取走,然后再去判断第二头牛在它的左边编号比它小的牛有m头,则是从剩下的牛的编号中,找出第m+1小的编号即可。反复下去,就可以找出全部牛的编号了;
也就是说,从后往前推,对于左边编号比它小的牛有i头,每次查询剩余编号中的第i+1小的数,就是该位置牛的编号、
 
解法:用线段树就来记录,某一段区间内剩下的编号数,从后往前位置判断当前这头牛的编号是多少,比如为i。在线段树种查找,剩下的编号第i+1大的编号。
线段树的关键值用来记录该区间内剩余编号的数目,我们只需要判断i+1是否大于左子树的剩余编号的数量,大于的话,说明该编号在右子树,否则在左子树,
在找编号的过程时,需要把包含该编号的区间的关键字(剩余数量编号-1),直到遇到叶子节点返回当前的编号。
用线段树每次找第K大的数字;
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef struct Line
 7 {
 8     int Left,Right;
 9     int Key;/*关键值,剩余编号的数目*/
10 }LR;
11 LR ID[100860];/*每一个节点都需要一个存储*/
12 int UP_Key(int n)
13 {
14     return ID[n*2].Key+ID[n*2+1].Key;
15 }
16 void Build(int L,int R,int n)    /*输入时建立二叉树根*/
17 {
18 
19     ID[n].Left=L;ID[n].Right=R;
20     if (L==R)/*找到根节点的时候结束*/
21     {
22         ID[n].Key=1;/*为L的编号存在*/
23         return;
24     }
25     int Mid=(L+R)/2;
26     Build(L,Mid,2*n);
27     Build(Mid+1,R,2*n+1);
28     ID[n].Key=UP_Key(n);/*更新编号数量*/
29 }
30 int Search(int Rank,int Step)
31 {
32     ID[Step].Key--;/*每次查询到编号的区间,都需把该区间的剩余编号的数目减1*/
33     if(ID[Step].Left==ID[Step].Right)
34     {
35         return ID[Step].Left;/*返回该编号*/
36     }
37 
38     if(Rank<=ID[Step*2].Key)/*找第Rank小的编号,先判断左子树数目是否大于rank的值*/
39        return Search(Rank,Step*2);/*若果大于的话,说明第Rank小的编号在左子树这边*/
40     else /*否则在右子树这边,且(找第Rank小的编号)在右子树这边变为第Rank-左子树编号小的比编号*/
41         return Search(Rank-ID[Step*2].Key,Step*2+1);
42 }
43 int main()
44 {
45     int N,i,a,b;
46     while(scanf("%d",&N)!=EOF)/*输入N,表示1~N区间*/
47     {
48         Build(1,N,1);
49         int Num[10000]={0};
50         for(i=1;i<N;i++)scanf("%d",&Num[i]);
51         for(i=N-1;i>=0;i--)
52         {
53             Num[i]=Search(Num[i]+1,1);
54         }
55         for(i=0;i<N;i++)
56             printf("%d\n",Num[i]);
57     }
58     return 0;
59 }
View Code

 

 
posted @ 2014-08-06 13:34  Wurq  阅读(255)  评论(0编辑  收藏  举报