【校内训练2019-11-15】跳一跳

【题目概括】

给定一个序列\(A\),请你从中取出一个最长的子序列,满足子序列的奇数项都严格大于偶数项或都严格小于偶数项。

【思路要点】

  • \(dp[i][0..1][0..1]\)表示当前为第\(i\)项,为选出子序列的奇数项还是偶数项,选择第一个决策还是第二个决策。
  • 可以发现\(DP\)方程满足之和前缀\(Max{dp}\)和后缀\(Max{dp}\)
  • 用树状数组优化。

【代码】

#include <bits/stdc++.h>

#define REP(i, s, t) for (int i = s; i <= t; i++)
#define PER(i, s, t) for (int i = s; i >= t; i--)
#define FI first
#define SE second
#define mp make_pair
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

template <class T>
void chkmax(T& x, T y) {
    x = max(x, y);
}
template <class T>
void chkmin(T& x, T y) {
    x = min(x, y);
}

template <class T>
void re(T& x) {
    x = 0;
    char ch = 0;
    int f = 1;
    for (; !isdigit(ch); ch = getchar())
        if (ch == '-')
            f = -1;
    for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    x *= f;
}

const int N = 1e5 + 5;
const int M = 1e6 + 5;

int n;
int a[N];

pii merge(pii a, pii b) { return mp(max(a.FI, b.FI), max(a.SE, b.SE)); }

struct fenwick {
    int lowbit(int x) { return x & -x; }

    pii tr[M][2];
    int lim;
    void setLim(int L) { lim = L; }

    void modify(int p, pii v0, pii v1) {
        for (; p <= lim; p += lowbit(p)) {
            tr[p][0] = merge(tr[p][0], v0);
            tr[p][1] = merge(tr[p][1], v1);
        }
    }

    pii query0(int p) {
        pii ans = mp(0, 0);
        for (; p; p -= lowbit(p)) ans = merge(ans, tr[p][0]);
        return ans;
    }

    pii query1(int p) {
        pii ans = mp(0, 0);
        for (; p; p -= lowbit(p)) ans = merge(ans, tr[p][1]);
        return ans;
    }
} bit1, bit2;

// bit1 maintain prefix dp max
// bit2 maintain suffix dp max

int dp[N][2][2];
int mx, ans;

int main() {
    freopen("jump.in", "r", stdin);
    freopen("jump.out", "w", stdout);
    re(n);
    for (int i = 1; i <= n; i++) re(a[i]), a[i]++, mx = max(mx, a[i]);
    bit1.setLim(mx), bit2.setLim(mx);
    for (int i = 1; i <= n; i++) {
        pii tmp1 = bit1.query0(a[i] - 1), tmp2 = bit1.query1(a[i] - 1);
        pii tmp3 = bit2.query0(mx - a[i]), tmp4 = bit2.query1(mx - a[i]);
        dp[i][0][0] = tmp1.SE + 1;
        dp[i][1][0] = tmp3.FI + 1;
        dp[i][0][1] = tmp4.SE + 1;
        dp[i][1][1] = tmp2.FI + 1;
        bit1.modify(a[i], mp(dp[i][0][0], dp[i][1][0]), mp(dp[i][0][1], dp[i][1][1]));
        bit2.modify(mx - a[i] + 1, mp(dp[i][0][0], dp[i][1][0]), mp(dp[i][0][1], dp[i][1][1]));
        dp[i][0][0] = dp[i][0][1] = 1;
        bit1.modify(a[i], mp(1, 0), mp(1, 0));
        bit2.modify(mx - a[i] + 1, mp(1, 0), mp(1, 0));
    }
    ans = 0;
    for (int i = 1; i <= n; i++)
        chkmax(ans, max(max(dp[i][0][0], dp[i][0][1]), max(dp[i][1][0], dp[i][1][1])));
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/chhokmah/p/11865705.html
今日推荐