「codeforces - 1674F」Madoka and Laziness
如果做过 codeforces - 1144G 那这题最多 *2200。
序列中的最大值必然为其中一个拐点,不妨设 \(a_p = a_\max\),先讨论另一个拐点 \(i\) 在 \(p\) 左侧的情况。于是问题转化为规划 \([1, i)\),\((i, p)\),\((p, n]\) 几个区间中的数给 \(i\) 还是给 \(p\)。
-
对于 \([1, i)\),令 \(dp[i]\) 表示将 \([1, i]\) 分为两个 strictly increasing subsequence,其中不以 \(i\) 结尾的 subsequence 的结尾元素的最小值,分讨转移即可。
-
对于 \((i, p)\),同 codeforces - 1144G,which is 这题唯一的难点。
-
对于 \((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";
}