UVA 10534 - Wavio Sequence LIS

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1475

题目大意:

给定一个长度为n的整数序列,求一个最长子序列(不一定为连续),使得该序列的长度为奇数2*k+1,前k+1个数严格递增,后k+1个数严格递减。(严格递增/递减意味着相邻两个数不能相同)

思路:

可以求两次LIS(最长上升子序列),一次是递增的,一次是递减的(其实就是倒着求递增的)

n高达10000,因此LIS要用二分查找来优化时间复杂度为O(nlogn)




#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=10000+10;
const int INF=0x7fffffff;
int data[MAXN],d1[MAXN],g1[MAXN],d2[MAXN],g2[MAXN];

int search(int L,int R,int x,int *g)
{
	while(L<R)
	{
		int mid=L+(R-L)/2;
		if(g[mid] < x)
			L=mid+1;
		else
			R=mid;
	}
	return L;
}
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		for(int i=0;i<n;i++)
			scanf("%d",&data[i]);

		for(int i=1;i<=n;i++) g1[i]=g2[i]=INF;
		for(int i=0,j=n-1;i<n;j--,i++)
		{
			//也可以直接用STL函数
			int k1=search(1,n+1,data[i],g1);//lower_bound(g1+1,g1+n+1,data[i])-g1;
			int k2=search(1,n+1,data[j],g2);//lower_bound(g2+1,g2+n+1,data[j])-g2;
			d1[i]=k1;
			d2[j]=k2;              //记录下标
			g1[k1]=data[i];      //求LIS
			g2[k2]=data[j];		//逆的LIS
		}
		int ans=1;
		for(int i=0;i<n;i++)
		{
			ans=max((2*min(d1[i],d2[i])),ans);
		}
		printf("%d\n",ans-1);
	}
	
	return 0;
}


posted @ 2014-02-12 23:58  hr_whisper  阅读(103)  评论(0编辑  收藏  举报