题意:
找一个最长(假设长度为2N-1)的子序列,使得前N个元素递增,后N个元素递减。
思路:
用nlogn的方法首尾各求一遍LIS,然后枚举中点就可以了。
注意要求中点两边一样长。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e5+5;
int n, a[maxn], b[maxn], dp1[maxn], dp2[maxn];
int main(void)
{
while(cin >> n)
{
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
int len = 1, l, r;
b[1] = a[1];
for(int i = 1; i <= n; i++)
{
l = 1, r = len;
while(l <= r)
{
int mid = (l+r)/2;
if(b[mid] < a[i]) l = mid+1;
else r = mid-1;
}
b[l] = a[i];
dp1[i] = l;
if(l > len) len++;
}
b[1] = a[n];
len = 1;
for(int i = n; i >= 1; i--)
{
l = 1, r = len;
while(l <= r)
{
int mid = (l+r)/2;
if(b[mid] < a[i]) l = mid+1;
else r = mid-1;
}
b[l] = a[i];
dp2[i] = l;
if(l > len) len++;
}
int ans = 0;
for(int i = 1; i <= n; i++)
if(min(dp1[i], dp2[i])*2-1 > ans)
ans = min(dp1[i], dp2[i])*2-1;
printf("%d\n", ans);
}
return 0;
}
本文介绍了一种求解最长增减子序列问题的有效算法,通过先分别计算最长递增子序列(LIS)和最长递减子序列(LDS),再找到中间点使两侧序列等长且最长。该算法复杂度为O(nlogn),适用于需要寻找特定结构子序列的问题。
1492

被折叠的 条评论
为什么被折叠?



