题意
有n头奶牛,已知它们的身高为 1~n 且各不相同,但不知道每头奶牛的具体身高。
现在这n头奶牛站成一列,已知第i头牛前面有Ai头牛比它低,求每头奶牛的身高。
输入格式
第1行:输入整数n。
第2..n行:每行输入一个整数Ai,第i行表示第i头牛前面有Ai头牛比它低。
(注意:因为第1头牛前面没有牛,所以并没有将它列出)
输出格式
输出包含n行,每行输出一个整数表示牛的身高。
第i行输出第i头牛的身高。
数据范围
1≤n≤$10^5$
输入样例:
5
1
2
1
0
输出样例:
2
4
5
3
1
分析
从后开始确定位置,用一个01序列表示高度从1-n的牛的高度是否被确定,如果确定就赋值为0。
寻找01序列的前缀和,前缀和等于A[i]时,前缀和的index+1就是该牛的高度,同时将01序列中对应值-1
关键在于寻找前缀合为A[i],树状数组和倍增刚好有重合的地方,设树状数组用t表示,倍增过程中可以直接用t[i]表示表示增加的区间和。
代码
#include <bits/stdc++.h>
#define N 100009
using namespace std;
int n,t[N],s[N],ans[N];
void add(int x,int y){
for(;x<=n;x+=x&-x){
t[x]+=y;
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++) add(i,1);
for(int i=2;i<=n;i++) cin>>s[i];
for(int i=n;i>0;i--){
int sum=0;
for(int p=log2(n);p>=0;p--){
if((1<<p)+ans[i]<=n && t[ans[i]+(1<<p)]+sum<s[i]+1){
sum+=t[ans[i]+(1<<p)];
ans[i]+=(1<<p);
}
}
add(++ans[i],-1);
}
for(int i=1;i<=n;i++) cout<<ans[i]<<endl;
return 0;
}