Acwing 244. 谜一样的牛

有n头奶牛,已知它们的身高为 1~n 且各不相同,但不知道每头奶牛的具体身高。

现在这n头奶牛站成一列,已知第i头牛前面有Ai头牛比它低,求每头奶牛的身高。

输入格式

第1行:输入整数n。

第2..n行:每行输入一个整数Ai,第i行表示第i头牛前面有Ai头牛比它低。
(注意:因为第1头牛前面没有牛,所以并没有将它列出)

输出格式

输出包含n行,每行输出一个整数表示牛的身高。

第i行输出第i头牛的身高。

数据范围

1≤n≤10^5

输入样例:

扫描二维码关注公众号,回复: 10293968 查看本文章
5
1
2
1
0

输出样例:

2
4
5
3
1
树状数组: 方便解决这类问题: 求一个数组内部元素动态变化着的数组中的第k大元素,建立树状数组的方式是以数组中元素的值作为索引

注意: 树状数组中的get_sum()操作,for循环时是从x开始每次i -= lowbit(i), 而不是从1开始每次i += lowbt(i)

下面的图像:在确定了一些牛的高度之后,get_sum(i)会出现不同i有着相同的get_sum()的值,这时候我们找的是每一个平台最左边的元素,因此二分时要注意其写法

#include<iostream>
using namespace std;

int h[100010],ans[100010];

int trie[100010],n;

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

int add(int x,int t){
    for (int i = x; i <= n; i += lowbit(i))
        trie[i] += t;
}

int get_sum(int x){
    
    int res = 0;
    
    for (int i = x; i ; i -= lowbit(i))   // 注意这里是从x开始向下减而不是从1开始增
        res += trie[i];
    
    return res;
}

int main(){
    
    cin>>n;
    
    for (int i = 1; i < n; ++i) {
        cin>>h[i];
        add(i,1);
    }
    
    add(n,1);
    
    for (int i = n - 1; i >= 0 ; --i){    // 倒着插入,每次最后一个元素就是当前剩下元素的第h[i] + 1小,因为它后面的元素都确定了高度
        
        int l = 1,r = n;
        
        while(l < r){
            int mid = l + r >> 1;
            if (get_sum(mid) >= h[i] + 1)
                r = mid;
            else l = mid + 1;
        }
        ans[i] = l;
        add(r,-1);
    }
    
    for (int i = 0; i < n; ++i)
        cout<<ans[i]<<endl;
    
    return 0;
}
发布了423 篇原创文章 · 获赞 38 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_41514525/article/details/105185096