POJ 2182 Lost Cows (线段树)

时间:2023-03-09 00:47:51
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\n",ans[i]);
return 0;
}