SHU 418 A序列

菜笔只会 O( n ^ 2 ) 的 LIS 的求法,现在补上……其实也非常好理解

这道题我记得很久很久之前就做过原题了,只要求两遍 LIS 即可,但是本来今天就OJ就很卡,好不容易交了两发,本以为两发都 WA 了 ,结果一发 waiting ,一发RE……

这里补上代码以备模板之需

题意:
找出左边递增右边递减,长度相同的子序列。

思路:
两遍LIS,同位置求最小。

#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define ll long long
#define each(i, n) for (int(i) = 0; (i) < (n); (i)++)
#define reach(i, n) for (int(i) = n - 1; (i) >= 0; (i)--)
#define range(i, st, en) for (int(i) = (st); (i) <= (en); (i)++)
#define rrange(i, st, en) for (int(i) = (en); (i) >= (st); (i)--)
#define fill(num, ary) memset((ary), (num), sizeof((ary)))

const int maxn = 5e+5;
int ary[maxn], st[maxn];
int dl[maxn], dr[maxn];

int main()
{
    int n;
    while (scanf("%d", &n) != EOF) {
        for (int i = 0; i < n; i++)
            scanf("%d", ary + i);
        memset(st, 0, sizeof st);
        st[1] = ary[0], dl[0] = dr[n - 1] = 1;
        int len = 1, pos;
        for (int i = 0; i < n; i++) {
            pos = lower_bound(st, st + len, ary[i]) - st;
            st[pos] = ary[i];
            len = max(len, pos + 1);
            dl[i] = pos;
        }
        memset(st, 0, sizeof st);
        st[1] = ary[n - 1], len = 1;
        for (int i = n - 1; i >= 0; i--) {
            pos = lower_bound(st, st + len, ary[i]) - st;
            st[pos] = ary[i];
            len = max(len, pos + 1);
            dr[i] = pos;
        }
        int ans = 0;
        for (int i = 0; i < n; i++)
            ans = max(ans, 2 * min(dl[i], dr[i]) - 1);
        printf("%d\n", ans);
    }
}

附上模板

int LIS()
{
    memset(dp, 0, sizeof(int)*n);
    int len = 1;
    dp[0] = a[0];
    for (int i = 1; i < n; ++i)
    {
        int pos = lower_bound(dp, dp + len, a[i]) - dp; //pos 为当前位置的最大上升子序列的长度
        dp[pos] = a[i];
        len = max(len, pos + 1);
    }
    return len;
}