这道题说是线段树,其实题意理解之后,分析可知:比最后一头牛的编号小的数为x,则这头牛的编号为x+1,比倒数第二投牛的编号小的数为y,则去掉所知牛的编号后,剩下的编号按从小到大的顺序数到第y+1个即刻。即:每次可以先知道最后一头牛的编号。
未用到线段树的代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main() {
int s[8010],i,ans,sort[8010],n,flag=1,rank[8010],index;
scanf("%d",&n);
index=n;
for(i=1; i<=n-1; i++) scanf("%d",&s[i]);
memset(sort,0,sizeof(sort));
for(i=n-1; i>0; i--) {
ans=0;
for(int j=1; j<=n; j++) {
if(ans==s[i]) {
for(; j<=n; j++) {
if(!sort[j]) {
rank[index--] = j;
sort[j] = 1;
break;
}
}
break;
}
if(!sort[j]) {
ans++;
}
}
}
for(i=1; i<=n; i++) {
if(!sort[i]) {
rank[index] =i;
break;
}
}
for(i=1; i<=n; i++) printf("%d\n",rank[i]);
return 0;
}
用到线段树的代码:
#include<iostream>
#include<cstdio>
using namespace std;
struct node{
int lc,rc,len;
}s[8000000];
void build(int left,int right,int index) {
int mid=(left+right)/2;
s[index].lc=left;
s[index].rc=right;
s[index].len= right-left+1;
if(left == right) return ;
build(left,mid,index*2);
build(mid+1,right,index*2+1);
}
int query(int num,int index) {
s[index].len--;
if(s[index].lc == s[index].rc) return s[index].lc;
if(s[index*2].len>=num) query(num,index*2);
else query(num-s[index*2].len,index*2+1);
}
int main() {
int n,a[8010],i,b[8010];
scanf("%d",&n);
build(1,n,1);
a[1]=0;
for(i=2; i<=n; i++){
scanf("%d",&a[i]);
}
int ans=n;
for(i=n; i; i--) {
b[ans--] = query(a[i]+1,1);
}
for(i=1; i<=n; i++ ) printf("%d\n",b[i]);
return 0;
}