题解:本题为找牛题,因为牛只有n头,身高也是各不相同的,所以,我们就可以建立一个树状数组来记录当前牛身高的牛是否使用过(树状数组里的值表示的是,当前牛是所有未使用过的牛中的第几高),因为树状数组是默认按升序排的,所以现在我们就只需要逆序遍历那个每头牛前面有多少头牛比它矮的arr数组(其中当前这头牛本身的值是arr[i] + 1),然后我们就二分找到树状数组中第arr[i] + 1身高的牛,然后记录下来,在从树状数组中将此牛减去,重复以上操作n次即可。
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1e5+7;
int n;
int tree[maxn]; //01标记N头牛是否使用过
int arr[maxn];
int ans[maxn];
int lowbit(int x) {
return x & (-x);
}
void add(int x, int val) {
while(x <= n) {
tree[x] += val;
x += lowbit(x);
}
}
int ask(int x) {
int res = 0;
while(x >= 1) {
res += tree[x];
x -= lowbit(x);
}
return res;
}
int main() {
scanf("%d", &n);
add(1, 1); //把所有的牛都加入树状数组
for(int i = 2; i <= n; i++) {
scanf("%d", &arr[i]);
add(i, 1);
}
for(int i = n; i >= 1; i--) { //需要逆序遍历找牛
int l = 1, r = n;
while(l < r) { //二分找按身高排序的第arr[i] + 1头牛(因为当前这头牛前面有arr[i]头牛比它矮,所以它自己就是第arr[i] + 1头牛)
int mid = (l + r) >> 1;
if(ask(mid) < arr[i] + 1) {
l = mid + 1;
} else {
r = mid;
}
}
ans[i] = r;
add(r, -1); //因为当前这头牛使用过了,所以就要减去(在树状数组中去掉标记)
}
for(int i = 1; i <= n; i++) {
printf("%d\n", ans[i]);
}
return 0;
}