poj 2182

题意:给出编号1~n的奶牛,是乱序的并且给出了每一个奶牛前小于自己序号的奶牛数目。输出奶牛的正确位置。

假设第i个奶牛的高度(就是指前面的小于自己序号的奶牛的数目)为Ai。因此第n个奶牛的序号必然是Ai+1。然后我们将这个奶牛砍掉,那么第n-1个奶牛就可以根据它的高度和已经判断出的第n个奶牛来确定。推出一般的情况:我们用Ck来保存1~k中确定的奶牛数(也就是我们砍掉的奶牛),因此还没有砍的奶牛数为(k-Ck);在倒序处理的过程中, 对于奶牛j,其高度为Aj+1,我们只要找出这样的k就行了:Aj+1==k-Ck

k-Ck代表了什么意思呢?其实就是在排好序的奶牛序列中,把已经确定的牛砍去之后k的高度。

Ck我们用树状数组来维护,k的查找我们可以用二分查找来优化。

  #include<cstdio>
  #include<iostream>
  using namespace std;
  #define MAX 80020
  int ok[MAX],sum[MAX],cow[MAX];
  int lowbit(int i)
  {
      return i & (-i);
  }
  int update(int i,int n)
  {
      while(i<=n)
      {
          sum[i]++;
          i+=lowbit(i);
      }
      return 0;
  }
  int GetSum(int i)
  {
      int s=0;
      while(i)
      {
          s+=sum[i];
          i-=lowbit(i);
      }
      return s;
  }
  int search(int k,int n)
  {
      int left=1,right=n,mid,temp;
      while(left<right)
      {
          mid=(left+right)>>1;
          temp=mid-GetSum(mid);
          if(temp<k) 
              left=mid+1;
          else
              right=mid;
      }
      return left;
  }
  int main()
  {
      int i,n;
      while(scanf("%d",&n)!=EOF)
      {
          memset(sum,0,sizeof(sum));
          memset(ok,0,sizeof(ok));
          for(i=2;i<=n;i++) scanf("%d",&cow[i]);
          for(i=n;i>0;i--)
          {
              int k=search(cow[i]+1,n);
              update(k,n);
              ok[i]=k;
          }
          
          for(i=1;i<=n;i++) printf("%d\n",ok[i]);
      }
      return 0;
  }
  

 

posted @ 2012-11-25 22:56  书山有路,学海无涯  阅读(955)  评论(0编辑  收藏  举报