[CF486E] LIS of Sequence

Description

给定一个数列,对于每个元素,问它属于以下哪一类:必须在最长上升子序列中;可能在最长上升子序列中,不可能在最长上升子序列中。

Solution

求每个元素开头和结尾的最长上升子序列长度 (f[i])(g[i])

如果 (f[i]+g[i]-1<ans),其中 (ans) 是整个序列的最长上升子序列,则 (i) 不可能在最长上升子序列中

如果存在 (j),使得 (f[i]=f[j], g[i]=g[j]),则 (i) 不在所有的最长上升子序列中

否则,(i) 一定在所有的最长上升子序列中

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1000005;

namespace lis
{
int n,a[N],f[N],g[N];
void solve()
{
    for(int i=0;i<=n;i++) g[i]=1e18;
    for(int i=1;i<=n;i++)
    {
        int pos=lower_bound(g+1,g+n+1,a[i])-g;
        g[pos]=a[i];
        f[i]=pos;
    }
}
}

int n,a[N],f[N],g[N];

signed main()
{
    ios::sync_with_stdio(false);

    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    lis::n=n;
    for(int i=1;i<=n;i++)
    {
        lis::a[i]=a[i];
    }
    lis::solve();
    for(int i=1;i<=n;i++)
    {
        f[i]=lis::f[i];
    }
    for(int i=1;i<=n;i++)
    {
        lis::a[i]=-a[n-i+1];
    }
    lis::solve();
    for(int i=1;i<=n;i++)
    {
        g[i]=lis::f[n-i+1];
    }
    int ans=*max_element(f+1,f+n+1);
    map<int,int> s;
    for(int i=1;i<=n;i++)
    {
        s[f[i]*1000000+g[i]]++;
    }
    for(int i=1;i<=n;i++)
    {
        if(f[i]+g[i]-1<ans) cout<<1;
        else if(s[f[i]*1000000+g[i]]>1) cout<<2;
        else cout<<3;
    }
}

原文地址:https://www.cnblogs.com/mollnn/p/13605706.html