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

谜一样的牛

有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
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;
}

你可能感兴趣的:(蓝桥杯)