Acwing 244. 謎一樣的牛

有n頭奶牛,已知它們的身高爲 1~n 且各不相同,但不知道每頭奶牛的具體身高。

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

輸入格式

第1行:輸入整數n。

第2..n行:每行輸入一個整數Ai,第i行表示第i頭牛前面有Ai頭牛比它低。
(注意:因爲第1頭牛前面沒有牛,所以並沒有將它列出)

輸出格式

輸出包含n行,每行輸出一個整數表示牛的身高。

第i行輸出第i頭牛的身高。

數據範圍

1≤n≤10^5

輸入樣例:

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章