poj(北大 2182) Lost Cows

Lost Cows
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 4143 Accepted: 2575

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

   
   基本思路:
           求一个从1-n的整数的序列,满足题目所给的要求。题目给出了n-1个ai的值,ai=m表示在第i(1<i<=n)个数的前面有m个数比第i个数小。我们要求的就是这第i个数是多少。所以只能从后往前找,因为在要求的序列中n个数必须且只能出现一次。然后就不断的查找,删除,最后求出整个序列。  数据,n=
5     

2  
2    
1

        首先从最后一个开始,表示第5个数前面有一个数小于它,所以这个数一定是2(因为每个数都要出现),然后是倒数第二个 ,表示第4个数字前面有2个数字小于第四个数,说明这个数字是在剩下的数字(除去这个数字以后的所有数字)里的名次排在第3(有两个比他小)。所以类推,从最后个数字开始,求出一个删除一个,第i个要求的数字就是当前所有(i个,前面已经找到了的删除掉)数字排在第ai+1的数字。
        显然,如果直接查找然后删除是可以完成的,但是时间复杂度为O(n^2),而题目是数据很大(n<8000),显然要超时。所以需要改进,不要整体操作,用线段数是很好的方法,可以将复杂读降低到O(n*log n).具体如下:
       

 1#include<iostream>
 2using namespace std;
 3int k,bj;
 4struct stu
 5{
 6 int len,rig;      //len为左儿子,rig右儿子
 7 int s;            //表示有多少个数字
 8}
a[30000];
 9void Lost(int n)           //建立线段树Lost,其实是一个中根遍历二叉树
10{                          //先遍历根结点,然后遍历左结点,最后遍历右结点
11  k++;
12  int j=k;
13  a[j].s=n;
14  if(n==1)             //当n=1的时候说明只有一个数,
15  {
16   a[j].len=bj++;  //用此结点的左儿子表示这个
17   a[j].rig=-1;    // 并用右儿子rig=-1作标记;
18   return ;
19  }

20 int i;
21 i=n/2;
22 a[j].len=k+1;
23 Lost(i);
24 a[j].rig=k+1;
25 Lost(n-i); 
26}

27void Delete(int i,int n)   //删除过程,其实也是一个查找过程,具有两个功能 :
28{                          //     查找和删除要求的点结点
29 a[i].s--;              //相当于删除一个点,所以总数减少1
30 if(a[i].rig==-1)       //  gig=-1说明到了叶子结点,查找完成
31 {
32  bj=a[i].len;
33  return ;
34 }

35 int j=a[i].len;
36 if(n<=a[j].s)
37 {
38  Delete(j,n);
39  return ;
40 }

41 else Delete(a[i].rig,n-a[j].s);
42}

43int main()
44{
45 int n,i;
46 int num1[8010],num2[8010];
47 while(scanf("%d",&n)!=EOF)
48 {
49  k=-1;bj=1;
50  Lost(n);
51  num2[0]=0;
52  for(i=1;i<n;i++)
53   scanf("%d",&num2[i]);
54  for(i=n-1;i>=0;i--)
55  {
56   Delete(0,num2[i]+1);
57   num1[i]=bj;
58  }

59  for(i=0;i<n;i++)
60   printf("%d\n",num1[i]);
61 }

62 return 0;
63}

64
65
66

posted on 2009-11-27 20:13 陈烈 阅读(507) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜