Solution -「CF 1674F」Madoka and Laziness

cirnovsky /

link。

如果做过 codeforces - 1144G 那这题最多 *2200。

序列中的最大值必然为其中一个拐点,不妨设 a_p = a_\max,先讨论另一个拐点 iipp 左侧的情况。于是问题转化为规划 [1,i)[1, i)(i,p)(i, p)(p,n](p, n] 几个区间中的数给 ii 还是给 pp

  • 对于 [1,i)[1, i),令 dp[i]dp[i] 表示将 [1,i][1, i] 分为两个 strictly increasing subsequence,其中不以 ii 结尾的 subsequence 的结尾元素的最小值,分讨转移即可。

  • 对于 (i,p)(i, p),同 codeforces - 1144G,which is 这题唯一的难点。

  • 对于 (p,n](p, n],同情况 1。

不太会写代码,,,参考了下 editorial,,,

#include <bits/stdc++.h>
#define cm(x, y) x = min(x, y)
#define cm2(x, y) x = max(x, y)
using namespace std;
int n, a[500100], pos, dp[500100], dp2[500100], dp3[500100][2];
int solve() {
    pos = n;
    for (int i=0; i<n; ++i) {
        if (a[i] > a[pos]) {
            pos = i;
        }
    }
    dp[0] = -1;
    for (int i=1; i<=pos; ++i) {
        dp[i] = 1e9;
        if (a[i] > dp[i-1]) {
            cm(dp[i], a[i-1]);
        }
        if (a[i] > a[i-1]) {
            cm(dp[i], dp[i-1]);
        }
    }
    dp2[n-1] = -1;
    for (int i = n-2; i>=pos; --i) {
        dp2[i] = 1e9;
        if (a[i] > dp2[i+1]) {
            cm(dp2[i], a[i+1]);
        }
        if (a[i] > a[i+1]) {
            cm(dp2[i], dp2[i+1]);
        }
    }
    int res = 0;
    dp3[pos][0] = dp[pos];
    for (int i=pos+1; i<n; ++i) {
        dp3[i][0] = 1e9;
        dp3[i][1] = -1e9;
        if (a[i-1] > a[i]) {
            cm(dp3[i][0], dp3[i-1][0]);
        }
        if (dp3[i-1][1] > a[i]) {
            cm(dp3[i][0], a[i-1]);
        }
        if (a[i-1] < a[i]) {
            cm2(dp3[i][1], dp3[i-1][1]);
        }
        if (dp3[i-1][0] < a[i]) {
            cm2(dp3[i][1], a[i-1]);
        }
        res += dp3[i][1] > dp2[i];
    }
    return res;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    for (int i=0; i<n; ++i) {
        cin >> a[i];
    }
    int ret = solve();
    reverse(a, a+n);
    cout << ret+solve() << "\n";
}