有n头奶牛,已知它们的身高为 1~n 且各不相同,但不知道每头奶牛的具体身高。
现在这n头奶牛站成一列,已知第i头牛前面有Ai头牛比它低,求每头奶牛的身高。
输入格式
第1行:输入整数n。
第2…n行:每行输入一个整数Ai,第i行表示第i头牛前面有Ai头牛比它低。
(注意:因为第1头牛前面没有牛,所以并没有将它列出)
输出格式
输出包含n行,每行输出一个整数表示牛的身高。
第i行输出第i头牛的身高。
数据范围
1≤n≤105
输入样例:
5
1
2
1
0
输出样例:
2
4
5
3
1
很像一次cf的div2第四题。但是那道题是小于的每个数字的和。
做法:我们每次找到最后面的一个0,然后让这个位置后面的全部都减一,最后我们要删除当前的数字,就直接赋值为inf即可。
AC代码;
#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e5+10,inf=0x3f3f3f3f;
int n,cnt,res[N];
struct node{
int l,r,mi,add;
}t[N<<2];
inline void push_up(int p){
t[p].mi=min(t[p<<1].mi,t[p<<1|1].mi);
}
inline void push_down(int p){
if(t[p].add){
t[p<<1].mi-=t[p].add; t[p<<1|1].mi-=t[p].add;
t[p<<1].add+=t[p].add; t[p<<1|1].add+=t[p].add;
t[p].add=0;
}
}
void build(int p,int l,int r){
t[p].l=l; t[p].r=r;
if(l==r){
if(cnt) scanf("%d",&t[p].mi); cnt++; return ;
}
int mid=l+r>>1;
build(p<<1,l,mid); build(p<<1|1,mid+1,r);
push_up(p);
}
void change(int p,int l,int r){
if(t[p].l==l&&t[p].r==r){
t[p].mi-=1; t[p].add+=1; return ;
}
push_down(p); int mid=t[p].l+t[p].r>>1;
if(r<=mid) change(p<<1,l,r);
else if(l>mid) change(p<<1|1,l,r);
else change(p<<1,l,mid),change(p<<1|1,mid+1,r);
push_up(p);
}
void updata(int p,int x){
if(t[p].l==t[p].r){
t[p].mi=inf; return ;
}
push_down(p); int mid=t[p].l+t[p].r>>1;
if(x<=mid) updata(p<<1,x);
else updata(p<<1|1,x);
push_up(p);
}
int ask(int p){
if(t[p].l==t[p].r) return t[p].l;
push_down(p); int mid=t[p].l+t[p].r>>1;
if(!t[p<<1|1].mi) return ask(p<<1|1);
else return ask(p<<1);
}
signed main(){
cin>>n; build(1,1,n);
for(int i=1;i<=n;i++){
int x=ask(1); res[x]=i; updata(1,x);
if(x!=n) change(1,x+1,n);
}
for(int i=1;i<=n;i++) printf("%d\n",res[i]);
return 0;
}