题目: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 ",i); break; } } for(int i=2;i<=n;i++){ printf("%lld ",a[i]); } }