1 给定一串数字,求一个子串满足一下要求:子串的长度是L=2*n+1,前n+1个数字是严格的递增序列,后n+1个数字是严格的递减序列,例如123454321就是满足要求的一个子串,输出满足要求的最长的L,
2、正着走一遍LIS,再倒着走一遍LIS,dp[i]表示前i个满足要求的数字的个数,那么dp1[i]和dp2[i]中最小的一个就是L的一半
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; const int INF=999999999; const int M=10010; int dp1[M],dp2[M],g[M],t[M]; int main() { int n; while(scanf("%d",&n)!=EOF) { memset(dp1,0,sizeof(dp1)); memset(dp2,0,sizeof(dp2)); for(int i=1; i<=n; i++) scanf("%d",&t[i]); fill(g,g+n,INF); //将一个区间里的元素都赋予INF值 for(int i=1;i<=n;i++) //寻找最长递增子序列 { int k=lower_bound(g+1,g+n+1,t[i])-g; //返回一个非递减序列中的第一个大于等于t[i]的位置 g[k]=t[i]; dp1[i]=max(dp1[i-1],k); } fill(g,g+n,INF); //反向,寻找最长递减子序列 for(int i=n; i>=1; i--) { int k=lower_bound(g+1,g+n+1,t[i])-g; g[k]=t[i]; dp2[i]=max(dp2[i+1],k); } int m=0; for(int i=1; i<=n; i++) m=max(m,min(dp1[i],dp2[i])); //找出最短的长度,才能保证是最长序列 printf("%d\n",2*m-1); } return 0; }