1. 程式人生 > 實用技巧 >#樹狀陣列,離散#C 波動序列

#樹狀陣列,離散#C 波動序列


分析

\(dp[i][j][0/1/2/3]\)表示前\(i\)個位置當前選的數為\(j\)
且選擇的是第一行/第二行/第三行不下降/第三行不上升,
狀態轉移方程顯然,用線段樹或者樹狀陣列維護一下就可以了


程式碼

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N = 100011;
int n, m, a[3][N], b[N * 3];
inline signed iut() {
    rr int ans = 0, f = 1;
    rr char c = getchar();
    while (!isdigit(c)) f = (c == '-') ? -f : f, c = getchar();
    while (isdigit(c)) ans = (ans << 3) + (ans << 1) + (c ^ 48), c = getchar();
    return ans * f;
}
inline signed max(int a, int b) { return a > b ? a : b; }
inline signed fan(int now) { return m - now + 1; }
struct Tree_Array {
    int c[N * 3];
    inline void update(int x, int y) {
        for (; x <= m; x += -x & x) c[x] = max(c[x], y);
    }
    inline signed query(int x) {
        rr int ans = 0;
        for (; x; x -= -x & x) ans = max(ans, c[x]);
        return ans;
    }
} h[3][2];
signed main() {
    freopen("sequence.in", "r", stdin);
    freopen("sequence.out", "w", stdout);
    n = iut();
    for (rr int i = 1; i <= n; ++i) a[0][i] = iut(), b[++m] = a[0][i];
    for (rr int i = 1; i <= n; ++i) a[1][i] = iut(), b[++m] = a[1][i];
    for (rr int i = 1; i <= n; ++i) a[2][i] = iut(), b[++m] = a[2][i];
    sort(b + 1, b + 1 + m), m = unique(b + 1, b + 1 + m) - b - 1;
    for (rr int i = 1; i <= n; ++i)
        a[0][i] = lower_bound(b + 1, b + 1 + m, a[0][i]) - b,
        a[1][i] = lower_bound(b + 1, b + 1 + m, a[1][i]) - b,
        a[2][i] = lower_bound(b + 1, b + 1 + m, a[2][i]) - b;
    for (rr int i = 1; i <= n; ++i) {
        rr int f1 = max(h[0][0].query(a[0][i]), max(h[1][0].query(a[0][i]), h[2][0].query(a[0][i]))) + 1;
        rr int f2 =
            max(h[0][1].query(fan(a[1][i])), max(h[1][1].query(fan(a[1][i])), h[2][1].query(fan(a[1][i])))) +
            1;
        rr int f3 = max(h[0][0].query(a[2][i]), h[1][0].query(a[2][i])) + 1,//一直不下降
               f4 = max(h[0][1].query(fan(a[2][i])), h[2][1].query(fan(a[2][i]))) + 1;//一直不上升
        h[0][0].update(a[0][i], f1), h[0][1].update(fan(a[0][i]), f1), h[0][0].update(a[1][i], f2),
            h[0][1].update(fan(a[1][i]), f2), h[1][0].update(a[2][i], f3), h[1][1].update(fan(a[2][i]), f3),
            h[2][0].update(a[2][i], f4), h[2][1].update(fan(a[2][i]), f4);
    }
    return !printf("%d", max(h[0][0].query(m), max(h[1][0].query(m), h[2][0].query(m))));
}