两遍动态规划加上快速的LIS算法,O(n*n)的LIS会超时,要用O(nlogn)的LIS,又学会了一些加速的技巧
#include <stdio.h>
int arr[10005];
int B[10005]; //该数组保存当前长度为i的递增子串的最小末尾元素的数值
int dp_ins[10005];
int dp_des[10005];
int _min(int a, int b){
return a<b ? a : b;
}
int find(int start, int end, int target){
int l, r, m;
bool find_target;
l = start; r = end-1;
find_target = false;
while(1){
if(l > r)
break;
m = (l+r) / 2;
if(B[m] == target)
break;
if(B[m]<target && B[m+1]>target){
find_target = true;
break;
}
if(target < B[m])
r = m-1;
else
l = m+1;
}
if(find_target)
return m;
else
return 0;
}
void func(int n){
int i, j, len, find_i;
int max;
B[1] = arr[1];
dp_ins[1] = 1;
len = 1;
for(i=2; i<=n; i++){
if(arr[i] > B[len]){
B[len+1] = arr[i];
len++;
dp_ins[i] = len;
continue;
}
if(arr[i] < B[1]){
B[1] = arr[i];
dp_ins[i] = len;
continue;
}
find_i = find(1, len, arr[i]);
if(find_i){
B[find_i+1] = arr[i];
}
dp_ins[i] = len;
}
B[1] = arr[n];
dp_des[n] = 1;
len = 1;
for(i=n-1; i>=1; i--){
if(arr[i] > B[len]){
B[len+1] = arr[i];
len++;
dp_des[i] = len;
continue;
}
if(arr[i] < B[1]){
B[1] = arr[i];
dp_des[i] = len;
continue;
}
find_i = find(1, len, arr[i]);
if(find_i){
B[find_i+1] = arr[i];
}
dp_des[i] = len;
}
max = 0;
for(i=1; i<=n; i++){
len = _min(dp_ins[i], dp_des[i]);
if(len > max)
max = len;
}
printf("%d\n", 2*max-1);
}
int main(void){
int n, i;
//freopen("input.dat", "r", stdin);
while(scanf("%d", &n) != EOF){
for(i=1; i<=n; i++) scanf("%d", arr+i);
func(n);
}
return 0;
}