题解:P16433 [APIO 2026 中国赛区] 上升
直接算贡献并不容易,考虑只要求
下文称标记点为该位置上的值确定的点。
考虑我们要求一定上升的一个段,若这个段中有超过
那么我们只要考虑相邻标记点之间的上升段,设这两个标记点的值为
称一对相邻标记点为一个段。
考虑延迟钦定,设
但是
rep (i, 0, n + 1) {
t[i][i] = 1;
rep (j, i, n) t[i][j + 1] = 1LL * t[i][j] * w[j] % mod;
}
dp[0][0] = 1;
auto work = [&](int L, int R) {
int p = a[L], q = a[R];
memset(f[L], 0, sizeof f[L]);
rep (i, L + 1, R) rep (j, 0, i) {
if (p + 1 + j >= i && i < R) rep (k, L + 1, i) {
int U = 1ULL * dp[k - 1][j] * C[p + 1 - k + j][i - k + 1] % mod * t[k][i] % mod;
inc(dp[i][j], U), inc(f[i][j], U);
}
if (i < R) {
int _u = (i - j <= L ? L : i - j + 1);
if (_u == L) dp[i][j] = (dp[i][j] + 1ULL * dp[L][j - i + L] * t[L][i] % mod * C[j][j - i + L]) % mod;
rep (k, max(L + 1, _u), i) {
dp[i][j] = (dp[i][j] + (1ULL * dp[k - 1][j - i + k - 1] * t[k][i]
+ 1ULL * f[k - 1][j - i + k - 1] * t[k - 1][i]) % mod * C[j][i - k + 1]) % mod;
}
} else {
int _u = max(i - q + p, L), les, val;
if (_u > L) ++ _u;
if (_u == L) {
les = q - p - i + L;
val = 1ULL * dp[L][j] * t[L][i] % mod * C[q - p - 1][i - L - 1] % mod;
rep (t, 0, min(j, les)) dp[R][j - t] = (dp[R][j - t] + 1ULL * val * C[les][t]) % mod;
}
rep (k, max(L + 1, _u), i) {
val = (1ULL * f[k - 1][j] * t[k - 1][i] + 1ULL * dp[k - 1][j] * t[k][i]) % mod * C[q - p - 1][i - k] % mod;
les = q - p - 1 - i + k;
rep (t, 0, min(j, les)) dp[R][j - t] = (dp[R][j - t] + 1ULL * val * C[les][t]) % mod;
}
}
}
};