Uva 10534 波浪子序列
题目链接:https://vjudge.net/contest/160916#problem/C
题意:
求一个奇数长的子序列,前一半严格递增,后一半严格递减;O(nlogn)
分析:
再次复习一下LIS算法;
严格递增:
g[k] : d[]值为 k 的最小元素,由于是严格递增,也就是说二分下界low_bound;
最长不下降:
也就是说upper_bound;
解析:二分函数,返回值是[L,R),也就是说不下降的时候,就是在后面插入一个;
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int inf = 0x3f3f3f3f; 6 const int maxn = 10000 + 5; 7 int a[maxn]; 8 int b[maxn]; 9 int d[maxn]; 10 int p[maxn]; 11 12 int g[maxn]; 13 14 int main() 15 { 16 int n; 17 while(scanf("%d",&n)!=EOF) { 18 for(int i=0;i<n;i++) { 19 scanf("%d",&a[i]); 20 //b[n-i-1] = a[i]; 21 } 22 //memset(d,0,sizeof(d)); 23 //memset(p,0,sizeof(p)); 24 //d[0] = 1; 25 //for(int i=1;i<n;i++) 26 //{ 27 // for(int j=0;j<i;j++) 28 // if(a[i]>a[j]) 29 // d[i] = max(d[i],d[j]+1); 30 //} 31 32 memset(g,inf,sizeof(g)); 33 for(int i=0;i<n;i++) { 34 int k = lower_bound(g+1,g+n+1,a[i])-g; 35 d[i] = k; 36 g[k] = a[i]; 37 } 38 39 //for(int i=n-2;i>=0;i--) { 40 // for(int j=n-1;j>i;j--) { 41 // if(a[i]>a[j]) 42 // p[i] = max(p[i],p[j]+1); 43 // } 44 //} 45 memset(g,inf,sizeof(g)); 46 for(int i=n-1;i>=0;i--) { 47 int k = lower_bound(g+1,g+n+1,a[i])-g; 48 p[i] = k; 49 g[k] = a[i]; 50 } 51 52 int ans = 1; 53 for(int i=0;i<n;i++) 54 if(d[i]!=1&&p[i]!=1) 55 ans = max(ans,2*min(d[i],p[i])-1); 56 printf("%d\n",ans); 57 58 } 59 60 return 0; 61 }