题目
题解思路
先将排列数的计数 插入树状数组 , 从最后一个数开始往前推 , 最后一个数在树状数组里的前缀和 (这里就是正序数 + 1 ) 必然等于 他的正序数 + 1(加上自己)。
我们可以利用二分来搜出这个数 。当这个数被求出后,我们在树状数组里删除他(因为我们是从后面往前推的,所以我们不能让后面的数对前面的数求正序数造成影响 )。
时间复杂度 O n log n log n
才250w
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2000010 ;
int a[ N ] , tre[ N ] ;
int n;
int ans [ N ] ;
int lbit(int x )
{
return x & ( -x );
}
void xg(int x , int y )
{
for (int i = x ; i <= n ; i += lbit(i) )
tre[i] += y;
}
int sum(int x )
{
int ans = 0 ;
for (int i = x ; i ; i -= lbit(i) )
ans += tre[i];
return ans;
}
int main ()
{
ios::sync_with_stdio(false);
cin >> n ;
for (int i = 2 ; i <= n ; i++ )
cin>>a[i];
for (int i = 1 ; i <= n ; i++ )
xg(i , 1 );
ans[n] = a[n] + 1 ;
xg ( a[n] + 1 , -1 );
for (int i = n-1 ; i >= 1 ; i-- )
{
int t1 = 1 , t2 = n ;
while( t1 < t2 )
{
int mid = (t1 + t2 )/2 ;
if ( sum(mid) >= a[i] + 1 )
t2 = mid ;
else
t1 = mid + 1 ;
}
xg ( t2 , -1 );
ans[i] = t2 ;
}
for (int i = 1 ; i <= n ; i++ )
{
cout << ans[i] <<"\n";
}
return 0 ;
}