这道题和卖票那道题目差不多,都是从前往后想不好想,从后往前想可以做的。
我们假设已经知道了所有数字的排列,那么对于最大的那个数,所有的数都比他小,所以,若他前面有N个数的话,那么N+1就是他的位置,这个最大数的位置就确定了,其他所有的数都比他小,所以,统计其他数前面有几个比这个数小的数的时候,最大数绝对不会被计算在内,所以可以把最大数所在的位置变成0,这样第二大的数就变成了最大的数,以此类推。
这道题也可以用树状数组做,查询的时候使用2分就可以了。
#include<stdio.h>
#include<string.h>
int dat[40000];
int n;
void PushUp(int rt)
{
dat[rt]=dat[rt*2]+dat[rt*2+1];
}
void build(int rt,int l,int r)
{
//printf("rt:%d l:%d r:%d\n",rt,l,r);
if(r-l==1)
{
dat[rt]=1;
}
else
{
int mid=(l+r)/2;
build(rt*2,l,mid);
build(rt*2+1,mid,r);
PushUp(rt);
}
}
void update(int rt)
{
}
int query(int rt,int l,int r,int x)
{
dat[rt]--;
//if(a>=r||l>=b) return -1;
if(r-l==1)
{
return l;
}
int mid=(l+r)/2;
int ls=rt*2;
int rs=rt*2+1;
if(x<=dat[ls])
{
return query(ls,l,mid,x);
}
else
return query(rs,mid,r,x-dat[ls]);
}
int num[20000];
int ans[20000];
int main()
{
scanf("%d",&n);
build(1,1,n+1);
for(int i=2;i<=n;i++)
{
scanf("%d",&num[i]);
}
for(int i=n;i>=1;i--)
{
int a=query(1,1,n+1,num[i]+1);
ans[i]=a;
}
for(int i=1;i<=n;i++)
{
printf("%d\n",ans[i]);
}
}
//树状数组+2分版
#include<stdio.h>
#include<string.h>
int bit[50000];
int n;
int sum(int x)
{
int s=0;
while(x)
{
s+=bit[x];
x-=(x&(-x));
}
return s;
}
void add(int i,int x)
{
while(i<=n)
{
bit[i]+=x;
i+=i&(-i);
}
}
int bifind(int x)
{
int lb=0,ub=n;
while(ub-lb>1)
{
int mid=(ub+lb)>>1;
int s=sum(mid);
if(s>=x)
ub=mid;
else
lb=mid;
}
return ub;
}
int num[10000];
int ans[10000];
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
scanf("%d",&num[i]);
}
for(int i=1;i<=n;i++)
add(i,1);
for(int i=n;i>=1;i--)
{
ans[i]=bifind(num[i]+1);
add(ans[i],-1);
}
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
}