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