发布时间: 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序列子串的长度。
样例输入1 复制 9 1 2 5 4 3 6 7 8 9 样例输出1 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; } 继续加油~