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
思路:我们遍历序列中每一个数字看看,对于每一个数字ai,以ai为中心,能得到的最长A序列是多少,这时先得到ai左边序列(以ai为序列末尾)的最长上升子序列left[i],再得到ai右边序列(包括ai)的最长下降子序列,最长下降子序列相当于序列倒着排的最长上升子序列,求得为right[i];
按A序列定义,ai的左右两边数字个数应该相等,那要使得ai为中心的A序列尽量大,可以去min(left[i],right[i])为A序列的长度的一半,2*min(left[i],right[i])-1即是以ai为中心A序列的最大长度,遍历ai,求最大长度。
AC代码:
#define _CRT_SECURE_NO_DEPRECATE #include <iostream> #include<cstdio> #include<vector> #include<queue> #include<cstring> #include<string> #include<stack> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f const int N_MAX = 500000+2; vector<int>vec; int dp[N_MAX]; int Right[N_MAX], Left[N_MAX]; int n; void LIS(const vector<int>&vec,int *a) { fill(dp,dp+n,INF); for (int i = 0; i < n;i++) { *lower_bound(dp,dp+n,vec[i])=vec[i]; a[i] = lower_bound(dp, dp + n, INF) - dp; } } int main() { while (scanf("%d",&n)!=EOF) { vec.clear(); vec.resize(n); for (int i = 0; i < n;i++) scanf("%d",&vec[i]); int ans=0; LIS(vec,Left); reverse(vec.begin(), vec.end()); LIS(vec, Right); int res=0; for (int i = 0; i < n;i++) { int ans = min(Right[i], Left[n-i]); res = max(res, ans); } printf("%d ",2*res-1); } return 0; }