传送门
大意:有一个1-n的排列,数据给出从第二个到第n个数中的每一个数前面有几个数比这个数小,要求还原这个1-n的排列
思路:最近做这种题好像有点感觉了,很自然的想到,我们可以从最后一个数来倒推,一直推出第一个过后就可以完事了。这样的话,我们很容易写出一个
N²
的算法。但作为一名OIer,我们要求上进,所以我们就会想,可不可以优化一下呢。其实我们发现,在找前面出现了几个比目标值小的操作很冗余,我们可以考虑用线段树来优化。那么我们就可以在
O(NlogN)
的时间内求出来整个序列
代码:
#include<cstdio>
#define MAXN 8005
struct node
{
int l, r, len;
}t[MAXN * 4];
void Build(int i, int l, int r)
{
t[i].l = l, t[i].r = r;
t[i].len = r-l+1;
if(l == r) return;
int mid = (l + r) >> 1;
Build(i<<1, l, mid);
Build(i<<1|1, mid + 1, r);
}
int Q(int i, int num)
{
-- t[i].len;
if(t[i].l == t[i].r) return t[i].l;
if(num > t[i<<1].len) return Q(i<<1|1, num - t[i<<1].len);
else return Q(i<<1, num);
}
int n, a[MAXN], ans[MAXN];
int main()
{
scanf("%d", &n);
Build(1, 1, n);
for(int i = 2; i <= n; i ++)
scanf("%d", &a[i]);
for(int i = n; i > 0; i --)
ans[i] = Q(1, a[i] + 1);
for(int i = 1; i <= n; i ++)
printf("%d\n", ans[i]);
}