SHU-A序列(两次最长上升子序列)

A序列

发布时间: 2017年7月9日 18:17   最后更新: 2017年7月9日 21:05   时间限制: 1000ms   内存限制: 128M

如果一个序列有奇数个正整数组成,不妨令此序列为a 1 ,a 2 ,a 3 ,...,a 2k+1  (0<=k ),并且a 1 ,a 2 ...a k+1  是一个严格递增的序列,a k+1 ,a k+2 ,...,a 2k+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;
}

继续加油~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值