题目链接:A序列
dp1[i]代表以第i个字符结尾的最长上升子序列的长度
dp2[i]代表以第i个字符开始的最长下降子序列的长度
用nlogn的算法更新这两个dp数组。最后的答案就是max(min(dp1[i], dp2[i]) * 2 - 1) (0 <= i < n)
代码如下:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAX_N = 500005;
void LIS(int a[], int n, int dp[])
{
int lis[MAX_N], len = 1;
lis[0] = a[0];
dp[0] = 1;
for (int i = 1; i < n; i++)
{
if (lis[len - 1] < a[i])
{
lis[len++] = a[i];
dp[i] = len;
}
else
{
int idx = lower_bound(lis, lis + len, a[i]) - lis;
lis[idx] = a[i];
dp[i] = idx + 1;
}
}
}
int main()
{
//freopen("test.txt", "r", stdin);
int n;
int a[MAX_N];
int dp1[MAX_N], dp2[MAX_N];
while (~scanf("%d", &n))
{
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
LIS(a, n, dp1);
reverse(a, a + n);
LIS(a, n, dp2);
reverse(dp2, dp2 + n);
int ans = -1;
for (int i = 0; i < n; i++)
ans = max(ans, min(dp1[i], dp2[i]) * 2 - 1);
printf("%d\n", ans);
}
return 0;
}