10534
要用两遍O(nlogn)的最长上升子序列。
//============================================================================ // Name : 10534.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <cstdio> #include <cstring> #include <map> #include <cmath> using namespace std; int n, Max, t, top; int a[10010], l[10010], r[10010], b[10010], stack[10010]; int main() { freopen("a.txt", "r", stdin); while(scanf("%d", &n)!=EOF){ for(int i = 1;i <= n;i++){ scanf("%d", &a[i]); b[n+1-i] = a[i]; l[i] = 1; r[i] = 1; } top = 1; stack[top] = a[1]; l[1] = 1; for(int i = 2;i <= n;i++){ if(a[i] > stack[top]){ top++; stack[top] = a[i]; l[i] = top; } else{ int tag = 0; int le = 1, ri = top, mid; while(le <= ri){ mid = floor((le+ri)/2); if(stack[mid] == a[i]){ break; } if(a[i] >= stack[mid]&&a[i] <= stack[mid+1]){ stack[mid+1] = a[i]; break; } if(le == ri){ if(a[i] < stack[le]){ stack[le] = a[i]; break; } } if(a[i] > stack[mid]){ le = mid; } else{ ri = mid; } } l[i] = top; } } top = 1; stack[top] = b[1]; r[1] = 1; for(int i = 2;i <= n;i++){ if(b[i] > stack[top]){ top++; stack[top] = b[i]; r[i] = top; } else{ int tag = 0; int le = 1, ri = top, mid; while(le <= ri){ mid = floor((le+ri)/2); if(stack[mid] == b[i]){ break; } if(b[i] >= stack[mid]&&b[i] <= stack[mid+1]){ stack[mid+1] = b[i]; break; } if(le == ri){ if(b[i] < stack[le]){ stack[le] = b[i]; break; } } if(b[i] > stack[mid]){ le = mid; } else{ ri = mid; } } r[i] = top; } } Max = 0; for(int i = 1;i <= n;i++){ // printf("%d %d\n\n", l[i], r[i]); t = min(l[i], r[n+1-i]); // printf("%d\n", t); if(Max < t*2-1){ Max = t*2-1; } } printf("%d\n", Max); } return 0; }