POJ 2182 Lost Cows (线段树)

题目大意: 有 n 头牛,编号为 1 - n 乱序排成一列,现已知每头牛前面有多少头牛比它的编号小,从前往后输出每头牛的编号。

思路: 从后往前推,假如排在最后的一头牛比他编号小的数量为a,那么它的编号必然为a+1。我们把编号为a+1的这头牛删掉,假如排在倒数第二的一头牛比他编号小的数量为b,那么该牛就为删掉最后一头牛后剩余牛中的第b+1头牛,我们可以照此思路下去...
问题就可以转化为搜索排在第k位的数为多少,我们可以用线段树来实现。

代码:

  #include<iostream>
  #include<cstdio>
  #include<cstdlib>
  #include<cstring>
  #include<queue>
  #include<algorithm>
  #include<cmath>
  #include<map>
  using namespace std;
  #define INF 0x7fffffff

  int ans[10000];
  struct node{
  	      int l,r,value;
  }a[40000];

  void buildtree(int i,int l,int r){
      a[i].l = l;
      a[i].r = r;
      a[i].value = 0;
      if(l == r)
          return ;
      int mid = (l + r) / 2 ;
      buildtree(i*2,l,mid);
      buildtree(i*2+1,mid+1,r);
  }

  void query(int no,int k,int num){
      a[no].value ++ ;
      if(a[no].l == a[no].r){
	      ans[k] = a[no].l;
	      return ;
      }
      if(a[no*2].r - a[no*2].l + 1 - a[no*2].value >= num)
          query(no*2,k,num);
      else{
	      num -= a[no*2].r - a[no*2].l + 1 - a[no*2].value ;
          query(no*2+1,k,num);
      }
  }

  int main(){
      int n,i,j,count[10000];
      cin >> n;
      count[1] = 0 ;
      buildtree(1,1,n);
      for(i=2;i<=n;i++)
          scanf("%d",&count[i]);
      for(j=n;j>0;j--){
   	      query(1,j,count[j]+1);
      }
      for(i=1;i<=n;i++)
          printf("%d
",ans[i]);
      return 0;
  }
原文地址:https://www.cnblogs.com/jxgapyw/p/4767939.html