[树状数组][二分查找] 谜一样的牛

谜一样的牛

有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


这题目是一个树状数组+二分的题目。
思路:因为每一个牛的编号都是从1-n的,所以如果找到i个牛比它小,那么它的编号就是i + 1。所以一个牛的编号就是统计一个牛前面的比它矮的马的数量+后面比它矮的马的数量 + 1。
题目给的序列是第i头牛前面有Ai头牛比它低。我们从后往前考虑,最后一个牛的Ai就是它的编号-1.
接下来,我们考虑到数第二个,我们需要找到在它后面的比它矮的数目加上前面的比它矮的数目就是一共比它矮的数目。这里我们使用树状数组加二分确定出答案。


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

int tree[maxn], w[maxn];
int n;

int lowbit(int x) {
    return x & (-x);
}

void add (int num, int x) {
    for (int i = num; i <= n; i += lowbit(i)) {
        tree[i] += x;
    }
}

int get_sum(int num) {
    int ans = 0;
    for (int i = num; i; i -= lowbit(i)) {
        ans += tree[i];
    }
    return ans;
}

int main () {
    cin >> n;
    w[1] = 0;
    for (int i = 2; i <= n; i++)    cin >> w[i];
    for (int i = 1; i <= n; i++)    add(i, 1);
    
    for (int i = n; i >= 1; i--) {
        int l = 1, r = n;
        while(l < r) {
            int mid = (l + r) >> 1;
            if (get_sum(mid) >= w[i] + 1) r = mid;
            else l = mid + 1;
        }
        w[i] = r;
        add(r, -1);
    }
    for (int i = 1; i <= n; i++) {
        cout << w[i] << "\n";
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值