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
",ans);
57 
58     }
59 
60     return 0;
61 }
View Code
原文地址:https://www.cnblogs.com/TreeDream/p/6777253.html