UVA10534-----Wavio Sequence-----动态规划之LIS
题目地址:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1475
题目意思:
给你一个序列,告诉你Wavio序列的定义
若一个Wavio序列的长度为2*n+1
前n+1个是递增的
后n+1个是递减的
求出这个序列中的最长的Wavio序列的长度
解题思路:
对序列正着求LIS得出dp1[i]反着求LIS得出dp2[i]分别代表以i为终点的正着的LIS的长度,反着的LIS的长度
然后枚举i,找出最大的min(dp1[i],dp2[i])
长度就是这个*2-1了
另外这题求LIS需要使用n*logn复杂度的算法
详见:http://blog.csdn.net/dangwenliang/article/details/5728363,写的很好
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 10000+20; int dp1[maxn]; int dp2[maxn]; int a[maxn]; int d[maxn]; int n; int find(int len,int ai) { int left=0; int right=len; while(left<=right) { int mid=(left+right)>>1; if(ai>d[mid]) left=mid+1; else if(ai<d[mid]) right=mid-1; else return mid; } return left; } int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } memset(d,0x3f3f3f3f,sizeof(d)); dp1[1] = 1; d[1]=a[1]; d[0]=-1; for(int i=2;i<=n;i++) { int j=find(n,a[i]); d[j]=a[i]; dp1[i]=j; } memset(d,0x3f3f3f3f,sizeof(d)); dp2[n] = 1; d[1]=a[n]; d[0]=-1; for(int i=n-1;i>=1;i--) { int j=find(n,a[i]); d[j]=a[i]; dp2[i]=j; } int ans = -1; for(int i=1;i<=n;i++) { int tmp = min(dp1[i],dp2[i]); if(ans < tmp*2-1) ans = tmp*2-1; } printf("%d\n",ans); } return 0; }