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