题意: 给定一个长度为n的整数序列,求一个最长子序列(不一定连续),使得该序列长度为奇数(2*k+1),且前k+1个数严格递增,后k+1个数严格递减(n<=10000)。
解法: 对原序列正着做一次最长上升序列,再逆序做一次最长上升序列。然后枚举每一个点,取每个点的正序最长序列长度和逆序最长序列长度的最小值中的最大值maxn,这个maxn只是答案的左半部分,所以答案是maxn*2-1。注意由于数据范围是1W,此处用n^2方法求最长上升序列要超时,只能用nlgn的方法。
/* **********************************************
Author : Nero
Created Time: 2013-8-25 16:08:36
Problem id : UVA 10534
Problem Name: Wavio Sequence
*********************************************** */
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define REP(i,a,b) for(int i=(a); i<(int)(b); i++)
#define clr(a,b) memset(a,b,sizeof(a))
const int INF = ~0u>>2;
int x[10100];
int n;
int d[10100];
int l[10100],r[10100];
int main() {
while(~scanf("%d", &n)) {
REP(i,1,n+1) {
scanf("%d", &x[i]);
}
REP(i,1,10100) d[i] = INF;
d[0] = 0;
REP(i,1,n+1) {
int pos = lower_bound(d,d+i,x[i]) - d;
l[i] = pos;
d[pos] = x[i];
}
REP(i,1,10100) d[i] = INF;
d[0] = 0;
for(int i = n; i >= 1; i -- ) {
int pos = lower_bound(d,d+i,x[i]) - d;
r[i] = pos;
d[pos] = x[i];
}
int maxn = 0;
REP(i,1,n) {
maxn = max(maxn, min(l[i],r[i]));
}
printf("%d\n", maxn*2-1);
}
return 0;
}