F - 最长上升子序列

你原本有一个 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;
}
  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值