大意不再赘述。
思路:一开始看错题,以为是从端点左边开始的最长上升子序列与下降子序列,后来发现是端点从左边开始的最长上升子序列,端点从右边开始的最长下降子序列。而且题目有一个陷阱,就是LIS不一定等于LDS,但序列一定是对称的,所以ans = max(ans, min(d1[i], d2[i])-1);
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
const int MAXN = 10010;
const int INF = 0x3f3f3f3f;
int A[MAXN];
int S[MAXN];
int d1[MAXN], d2[MAXN];
int n, m;
void init()
{
for(int i = 1; i <= n; i++) S[i] = INF;
}
int BSearch(int x, int y, int v)
{
while(x <= y)
{
int m = x+(y-x)/2;
if(S[m] < v) x = m+1;
else y = m-1;
}
return x;
}
void LIS(int n)
{
init();
int ans = 0;
for(int i = 1; i <= n; i++)
{
int x = 1, y = i;
int pos = BSearch(x, y, A[i]);
d1[i] = pos;
S[d1[i]] = min(S[d1[i]], A[i]);
ans = max(ans, d1[i]);
}
}
void LDS(int n)
{
init();
int ans = 0;
for(int i = n; i >= 1; i--)
{
int x = 1, y = i;
int pos = BSearch(x, y, A[i]);
d2[i] = pos;
S[d2[i]] = min(S[d2[i]], A[i]);
ans = max(ans, d2[i]);
}
}
void read_case()
{
for(int i = 1; i <= n; i++) scanf("%d", &A[i]);
}
/*int check(int a, int b)
{
if(a == b && (a+b-1) & 1) return 1;
return 0;
}*/
void solve()
{
read_case();
int ans = 0;
LIS(n), LDS(n);
for(int i = 1; i <= n; i++)
{
ans = max(ans, 2*min(d1[i], d2[i])-1);
//if(check(d1[i], d2[i])) ans = max(ans, (d1[i]+d2[i]-1));
//printf("%d %d\n", d1[i], d2[i]);
}
printf("%d\n", ans);
}
int main()
{
while(~scanf("%d", &n))
{
solve();
}
return 0;
}