你原本有一个 1 到 n 的排列,但是不慎地,你遗忘了它,但是你记得以 第i个位置 结尾的最长上升子序列的长度数组 {an} ,现在希望你能够构造一个符合条件的排列 p ,如果不存在符合上述条件的排列 p ,则输出 - 1。
这里定义以 第i位置 结尾的最长上升子序列的长度,为符合以下条件的整数数组 中 k 的最大值。
本题输入输出量比较大,请选手注意。
Input
第一行一个整数 n (1 ≤ n ≤ 106)
第二行 n 个整数表示数组 {an} (1 ≤ ai ≤ n),其中 ai 表示以 i 结尾的最长上升子序列的长度。
Output
一行 n 个整数表示排列 p ,如果无解,则输出 - 1。
Examples
Inputcopy Outputcopy
5
1 2 2 3 3
1 5 2 4 3
Inputcopy Outputcopy
7
1 1 2 1 4 4 4
-1
题目大意:给出在以i位置结尾的最长的升序子序列,构造原序列
解题思路:参考学长代码
如果在i位置上最长长度相同,那么这些位置上的数据一定是倒序排列的
例如
1 1 1 1
可构造为
4 3 2 1
每个位置上的最大子序列长度都是1
所以存入数据(放入数组中,输出时要使用)时判断该长度出现次数,
存完再顺序判断1-n,出现哪个就依次输出对应出现的数字;具体方法放在代码中
因为i位置上为到当前位置最长的子序列长度,所以存入数据时要判断该数据前面数据是否存在该长度-1的最大子序列,如果不存在,无论如何都不能达到该数据的最长子序列输出-1;
代码实现
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N=1e6+10;
int a[N],b[N],c[N];
int k=0;
signed main()
{
std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int n;cin>>n;
int ans=0,cnt=1;
b[0]=1;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(b[a[i]]==0)
{
cnt++;
}
b[a[i]]++;
if(b[a[i]-1]==0)
{
ans=1;
break;
}
}
if(ans==1) cout<<"-1";
else
{
int sum=0;
for(int i=1;i<=cnt;i++)
{
sum+=b[i];
c[i]=sum;
}
for(int i=1;i<=n;i++)
{
cout<<c[a[i]]<<" ";
c[a[i]]--;
}
// for(int i=1;i<=cnt;i++)
// {
// cout<<c[i]<<" ";
// }
}
return 0;
}