244. 谜一样的牛

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

思路

计算末尾的牛身高的时候,可以发现就是求他在剩余可选身高中排第几的问题。可以用树状数组算query(r):前r身高还有多少个。这样对于一头牛说,前面比他低的还有t牛,那么就需要找到第一个query(r) == t+1 ,r就是这头牛的身高。因为树状数组是计算前缀和,所以可以二分操作这个过程

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;

int N;
int arr[maxn],ans[maxn];
int tr[maxn];

int lowbit(int x){
    return x&-x;
}
void add(int idx,int v){
    for(int i = idx;i<=N;i += lowbit(i)) tr[i] += v;
}
int query(int r){
    int sum = 0;
    for(int i = r;i>=1;i -= lowbit(i)) sum += tr[i];
    return sum;
}
int main(){
    cin>>N;
    for(int i = 1;i<=N;i++) add(i,1);
    for(int i = 2;i<=N;i++) scanf("%d",&arr[i]);
    for(int i = N;i>=1;i--){
        int l = 1,r = N,mid;
        while(l<r){
            mid = (l+r)>>1;
            if(query(mid)  >= arr[i] + 1) r = mid;
            else l = mid+1;
        }
        ans[i] = l;
        add(l,-1);
    }
    for(int i = 1;i<=N;i++) printf("%d\n",ans[i]);

    return 0;
}