A序列
发布时间: 2017年7月9日 18:17 最后更新: 2017年7月9日 21:05 时间限制: 1000ms 内存限制: 128M
如果一个序列有奇数个正整数组成,不妨令此序列为a 1 ,a 2 ,a 3 ,...,a 2∗k+1 (0<=k ),并且a 1 ,a 2 ...a k+1 是一个严格递增的序列,a k+1 ,a k+2 ,...,a 2∗k+1 ,是一个严格递减的序列,则称此序列是A序列。
比如1 2 5 4 3就是一个A序列。
现在Jazz有一个长度为n 的数组,他希望让你求出这个数组所有满足A序列定义的子序列里面最大的那个长度。(子序列可以不连续)
比如1 2 5 4 3 6 7 8 9,最长的A序列子串是1 2 5 4 3。
多组输入,每组两行。
第一行是n ,表示给的数组的长度。
第二行有n 个数(int范围),即给你的数组。
1<=n<=500000 。
每组输入输出一行,即最长的A序列子串的长度。
复制
9 1 2 5 4 3 6 7 8 9
5
思路:维护每个点的从左边到该点的最长上升子序列和从右边到该点的最长上升子序列(该点必选),最后扫一遍每个点选择较短的Lis-1,再*2+1即是所求。
Code:
#include <algorithm>
#include <iostream>
#include <string.h>
#include <cstdio>
#define LL long long
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 500005;
int a[maxn], dp1[maxn], dp2[maxn], num[maxn];
int main()
{
int n, tot;
while(~scanf("%d", &n))
{
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
tot = 0;
num[tot++] = a[1];
dp1[1] = 1;
for(int i = 2; i <= n; ++i)
{
if(a[i] > num[tot-1]) num[tot++] = a[i], dp1[i] = tot;
else
{
int id = lower_bound(num, num+tot, a[i])-num;
num[id] = a[i];
dp1[i] = id+1;
}
}
tot = 0;
num[tot++] = a[n];
dp2[n] = 1;
for(int i = n-1; i >= 1; --i)
{
if(a[i] > num[tot-1]) num[tot++] = a[i], dp2[i] = tot;
else
{
int id = lower_bound(num, num+tot, a[i])-num;
num[id] = a[i];
dp2[i] = id+1;
}
}
int ans = 1;
for(int i = 1; i <= n; ++i)
{
ans = max(ans, (min(dp1[i], dp2[i])-1)*2+1);
}
printf("%d\n", ans);
}
return 0;
}
继续加油~