喜闻乐见的大水题。
先离散化,求一下正的最长上升子序列,再求一下反的最长下降子序列。然后看这两个加起来等不等于|lis|+1,然后如果能做某个位置的只出现一次,它就是不可替代的。(看代码吧
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int N=50005;
int t[N],n,a[N],lsh[N],cnt[N],tot,g[N],f[N];
void add(int i,int mx){
for(;i<=n;i+=i&-i) t[i]=max(mx,t[i]);
}
int query(int i){
int ans=0;
for(;i;i-=i&-i) ans=max(ans,t[i]);
return ans;
}
int ans,u;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),lsh[i]=a[i];
sort(lsh+1,lsh+1+n);u=unique(lsh+1,lsh+1+n)-lsh-1;
for(int i=1;i<=n;i++)
a[i]=lower_bound(lsh+1,lsh+1+u,a[i])-lsh,
f[i]=query(a[i])+1,add(a[i],f[i]),ans=max(ans,f[i]);
memset(t,0,sizeof t);
for(int i=n;i;i--) g[i]=query(u-a[i]+1)+1,add(u-a[i]+1,g[i]);
for(int i=1;i<=n;i++) if(f[i]+g[i]==ans+1) lsh[++tot]=i,cnt[f[i]]++;
printf("A:");
for(int i=1;i<=tot;i++) if(cnt[f[lsh[i]]]!=1) printf("%d ",lsh[i]);
printf("
B:");
for(int i=1;i<=tot;i++) if(cnt[f[lsh[i]]]==1) printf("%d ",lsh[i]);
}