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;
}
}