UVA 10534 Wavio Sequence DP(LIS+二分)

点击打开链接

题意:Wavio序列定义为:长度L=2*n+1 前n+1个严格递增,后n+1个严格递减,给出n个数求满足Wavio的最长子序列



Wavio序列中间点最大,若中间点k,则其长度取决于min(LIS[k],LDS[k]),n<=1e4,O(nlogn)求出以k结尾和开头的LIS,LDS 枚举中间点k即可


L[x]:LIS长度为X的最小a[j] 若L递增 则找到最后一个x,L[x]<a[i] 则a[i]结尾LIS长度为X+1,更新L[x+1]即可 

初始时L递增,每次将L[x+1]更新为a[i]时,L[x+1]=a[i]>L[x] 每次更新后依然递增,归纳可得L[0]<L[1]....<L[n] 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=1e9;
const int N=2e5+20;
int n,a[N],f[N],g[N];
int L[N];
int main()
{
	while(cin>>n)
	{
		for(int i=1;i<=n;i++)
			cin>>a[i];
		for(int i=1;i<=n;i++)
			L[i]=inf;
		L[0]=-inf;
		for(int i=1;i<=n;i++)
		{
			int l=0,r=n;
			while(l<=r)
			{
				int mid=(l+r)>>1;
				if(L[mid]<a[i])
				l=mid+1;
				else
				r=mid-1;	
			}
			f[i]=l;
			L[l]=a[i];//L[l]>a[i]更新
		}
		for(int i=1;i<=n;i++)
			L[i]=inf;
		L[0]=-inf;
		for(int i=n;i>=1;i--)
		{
			int l=0,r=n;
			while(l<=r)
			{
				int mid=(l+r)>>1;
				if(L[mid]<a[i])
				l=mid+1;
				else
				r=mid-1;	
			}
			g[i]=l;
			L[l]=a[i];//更新 
		}	
		int ans=0;
		for(int i=1;i<=n;i++)
			ans=max(ans,min(f[i],g[i]));
		cout<<ans*2-1<<endl; 			
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值