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;
}