题目:https://www.acwing.com/problem/content/245/

题意:有n只牛,现在他们按一种顺序排好,现在知道每只牛前面有几只牛比自己低,牛的身高是1-n,现在求每只牛的身高

思路:我们可以考虑最后一只牛,最后一只牛前面比他低的有 a[n]只,那么他的身高就是 a[n]+1

假设这只取的是  1   ,倒数第二只牛  a[n-1]=1  ,说明前面有一只比他低,但是他不能直接取2,因为后面已经取了1,但是前面还有比他低的,说明每一步只能是在现有没被选的中选a[i]+1大的身高,然后确定身高的话我们用一个数组b[i],代表这个是否被选,为了方便树状数组取值,我初值都设为1,然后树状数组取前缀和就是代表比当前身高低的个数,然后我们二分找身高即可

 

 

#include<bits/stdc++.h>
#define maxn 100005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll n,a[maxn],b[maxn],c[maxn];
ll lowbit(ll x){
    return x&(-x);
}
void add(ll x,ll y){
    while(x<=n){
        c[x]+=y;
        x+=lowbit(x);
    }
}
ll query(ll x){
    ll sum=0;
    while(x){
        sum+=c[x];
        x-=lowbit(x);
    }
    return sum;
}
int main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        b[i]=1;
        add(i,1);
    }
    for(int i=2;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=n;i>=2;i--){
        ll l=0,r=n+1,ans;
        while(l<r){
            ll mid=(l+r)/2;
            if(query(mid)>=a[i]+1){
                ans=mid;
                r=mid;
            } 
            else l=mid+1;
        } 
        a[i]=ans;
        b[ans]=0;
        add(ans,-1);
    }
    for(int i=1;i<=n;i++){
        if(b[i]){
            printf("%lld\n",i);
            break;
        }
    }
    for(int i=2;i<=n;i++){
        printf("%lld\n",a[i]);
    }
}