[51nod1218]最长递增子序列 V2

喜闻乐见的大水题。
先离散化,求一下正的最长上升子序列,再求一下反的最长下降子序列。然后看这两个加起来等不等于|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]);
}
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9642537.html