谜一样的牛
我们不难发现,从所给的数列的末尾开始倒着推,是可以得到答案的。开一个树状数组表示每一个身高 i 还可以用 tr [ i ](0 / 1) 次。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 100010
using namespace std;
int n;
int a[N], tr[N], height[N];// height数组用来记录每头牛的身高
int lowbit(int u)
{
return u & -u;
}
void add(int x, int c)
{
for (int i = x; i <= n; i += lowbit(i))
tr[i] += c;
}
int ask(int x)
{
int res = 0;
for (int i = x; i > 0; i -= lowbit(i))
res += tr[i];
return res;
}
int main()
{
cin >> n;
for (int i = 2; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) // 每个身高可以用1次
add(i, 1);
for (int i = n; i > 0; i--)
{
int k = a[i] + 1; // 第i头牛的身高在剩下的可用身高中排名为k(由小到大)
int l = 1, r = n; // 用二分搜索减小时间复杂度(相当于是在以ask为值的递增数列中查找k)
while(l < r)
{
int mid = l + r >> 1;
if(ask(mid) >= k) r = mid;
else l = mid + 1;
}
height[i] = r;
add(r, -1); // 把这个身高可使用次数减为0
}
for (int i = 1; i <= n; i++)
printf("%d\n", height[i]);
return 0;
}