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; }
新 blog : www.hrwhisper.me