题目的意思就是从给出的一串数字中找出一个长度是奇数的子串.
假设中点是第k个.
那么前k个是递增序列,后k个是递减序列.
例如1 2 3 4 5 4 3 2 1
1 2 4 8 9 7 6 3 1
所以我们就是要求正方向的最长递增子序列 和 逆方向的最长递增子序列.再进行进行比较.
比如以第 5 个数字为中心.它构成的正方向最长递增序列长度f[5] = 6 ,构成的负方向最长递增子序列 d[5] = 4;
那么他构成的目标样子的串长度就是 4 * 2 - 1.
但是要注意一点.普通的O(n^2)的最长增长子序列算法会超时.
要用O(nlogn)的.
AC代码:
#include<stdio.h>
#include<string.h>
const int N = 10005;
int num[N];
int b[N];
int f[N];
int d[N];
int main () {
int t ;
while (~scanf("%d",&t)) {
int len;
for (int i = 1 ; i <= t ; i++) {
scanf("%d",&num[i]);
}
b[1] = num[1];
len = 1;
f[1] = 1;
for (int i = 2 ; i <= t ; i++) {
if(num[i] <= b[1]) {
b[1] = num[i];
f[i] = len;
continue;
}
if (num[i] > b[len]) {
b[++len] = num[i];
f[i] = len;
continue;
}
for (int j = 1 ; j < len ;j++) {
if(num[i] > b[j] && num[i] <= b[j + 1]) {
b[j + 1] = num[i] ;
f[i] = len;
}
}
}
b[1] = num[t];
len = 1;
d[t] = 1;
for (int i = t - 1 ; i >= 1 ; i--) {
if(num[i] <= b[1]) {
b[1] = num[i];
d[i] = len;
continue;
}
if (num[i] > b[len]) {
b[++len] = num[i];
d[i] = len;
continue;
}
for (int j = 1 ; j < len ;j++) {
if(num[i] > b[j] && num[i] <= b[j + 1]) {
b[j + 1] = num[i] ;
d[i] = len;
continue;
}
}
}
int m = 0;
int temp;
for (int i = 1 ; i <= t ;i++) {
temp = f[i] < d[i] ? f[i] : d[i];
if (temp > m)
m = temp;
}
printf("%d\n",m * 2 - 1);
}
}