UVA - 10534 Wavio Sequence 【最长上升子序列变形】 好题

传送门
题意: 给定一个n个数的序列, 问其中最长的波浪序列有多长, 波浪序列的定义为 :
首先长度是奇数, 即2*n + 1, 并且前面(n + 1) 个元素严格单增 , 后面(n + 1) 个元素严格单减.

思路: 很明显我们并不能一次就可以得出答案, 但是我们可以枚举以每个数作为浪尖时的答案, 然后取max就好了, 所以我们首先要预处理出以每个元素为结尾的前面的最长上升子序列, 后该位置后面的最长下降子序列, 最长下降子序列我们反过来求就变成了最长上升子序列乐, 这样预处理后, 枚举每一个元素作为浪尖, 因为是对称的n个元素, 所以要取两边的min值来计算答案.
细节请看代码实现:

const int maxn = 5e5+5;
int dp1[maxn], dp2[maxn];
int g[maxn], a[maxn];
int n;
void LIS() {
    Fill(g, inf);
    for (int i = 1 ; i <= n ; i ++) {
        int pos = lower_bound(g+1, g+1+n, a[i]) - g;
        dp1[i] = pos;
        g[pos] = a[i];
    }
}
void LIS2() {
    Fill(g, inf);
    for (int i = n ; i >= 1 ; i --) {
        int pos = lower_bound(g+1, g+1+n, a[i]) - g;
        dp2[i] = pos;
        g[pos] = a[i];
    }
}
void solve()
{
    while(~scanf("%d", &n)) {
        for (int i = 1 ; i <= n ; i ++) {
            scanf("%d", &a[i]);
        }
        LIS(); LIS2();
        int ans = 0;
        for (int i = 1 ; i <= n ; i ++) {
            ans = max(ans, (min(dp1[i], dp2[i])-1)*2 + 1);
        }
        printf("%d\n", ans);
    }
}

你可能感兴趣的:(序列dp)