本题可以用2种方法:模拟 树状数组(线段树)+二分
/*
题意:一群牛的编号为1~n,现在乱站成一列,fj记录下来了每头牛
前面编号比它编号小的牛的头数,求各个位置上牛的编号
解法:逆序模拟。假如排在最后的一头牛比他编号小的数量为a,
那么它的编号必然为a+1。我们把编号为a+1的这头牛删掉(标记为已经排过),
假如排在倒数第二的一头牛比他编号小的数量为b,那么该牛就
为没被标记过的牛中的第b+1头牛。
*/
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=8005;
int cow[MAXN],num[MAXN],vis[MAXN];
//比它编号小的牛的头数,最终位置,标记数组
int main()
{
int n,ans;
while(cin>>n)
{
ans=0;
memset(vis,0,sizeof(vis));//初始化为全部没标记过。
for(int i=1;i<n;i++)
{
cin>>cow[i];
}
for(int i=n-1;i>0;i--)//逆序模拟
{
int top=0,j=0;
while(top<=cow[i])
{
j++;
if(!vis[j])
{
top++;
}
}
num[ans++]=j;
vis[j]=1;
}
for(int j=1;j<=n;j++)//最后只剩下一头牛没被计算过。
{
if(!vis[j])
{
num[ans]=j;
break;
}
}
for(int i=ans;i>=0;i--)
{
cout<<num[i]<<endl;
}
}
return 0;
}
/*
树状数组+二分查找
*/
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=8005;
int cow[MAXN],num[MAXN],c[MAXN];
int n,ans;
int lowbit(int x)
{
return x&(-x);
}
int sum(int i)
{
int s=0;
while(i>0)
{
s+=c[i];
i-=lowbit(i);
}
return s;
}
void add(int i,int val)
{
while(i<=n)
{
c[i]+=val;
i+=lowbit(i);
}
}
int find(int m)//求剩下的牛当中第m个位置的牛的编号
{
int l=1,r=n,mid,va;
while(r>=l)
{
mid=(l+r)>>1;
va=sum(mid);
if(va>=m)
{
r=mid-1;
}
else
{
l=mid+1;
}
}
return l;//返回的是sum(l)==m
}
int main()
{
while(cin>>n)
{
ans=0;
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
{
add(i,1);
}
for(int i=1;i<n;i++)
{
cin>>cow[i];
}
for(int i=n-1;i>0;i--)
{
num[ans]=find(cow[i]+1);//比他编号小的数量为cow[i],
//那么该牛就为没被标记过的牛中的第cow[i]+1头牛。
add(num[ans],-1);//标记这个位置的牛已经被访问过
ans++;
}
for(int i=1;i<=n;i++)//最后只剩一头牛没被计算过
{
if(c[i])
{
num[ans]=i;
break;
}
}
for(int i=ans;i>=0;i--)//逆序输出位置
{
cout<<num[i]<<endl;
}
}
return 0;
}