题解:AWTF2026B Window Records

超级大神题!

先把区间前缀最大值个数转成后缀前缀最大值个数。具体来说,令 \(h_i\) 表示 \(p[i..2n-1]\) 的前缀最大值个数,那么一个区间 \(p[l..r]\) 的前缀最大值个数就是 \(h_l-\min\limits_{l\leq i\leq r}h_i+1\)。

证明

令 \(h_{n+1}=0\)。设 \(nxt_i\) 为 \(p_i\) 右边第一个 \(>p_i\) 的位置,不存在记为 \(n+1\)。那么显然有:

  • \(h_i=h_{nxt_i}+1\)。
  • \(\forall i<j<nxt_i,h_j\geq h_i\)。

由此不难得出结论。\(\Box\)

先考虑怎样的 \(h\) 是合法的。显然要满足 \(h_i\geq 1\) 且 \(h_i\leq h_{i+1}+1\)。不难发现这也是充分的:可以归纳构造,每次取最靠前的满足 \(h_i=1\) 的位置放最大值,然后给左边的 \(h\) 全体减 \(1\),两边分别构造即可。

于是现在对于序列 \(x\),我们要判断是否存在一组合法的 \(h\),使得 \(x_i=h_i-\min\limits_{i\leq j\leq i+n-1}h_j+1\)。

观察到每个滑动窗口都包含 \(h_n\),考虑从 \(h_n\) 劈开,令 \(r_i=\min\limits_{n\leq j\leq i+n-1}h_j\),限制变成 \(x_i=h_i-\min\left(\min\limits_{i\leq j\leq n}h_j,r_i\right)+1\)。显然 \(r_1=h_n,r_n=1\),而且由 \(h\) 的限制不难得出 \(0\leq r_i-r_{i+1}\leq 1\)。反过来对于一组满足条件的 \(r\),我们直接令 \(h_{i+n-1}=r_i\) 即可保证 \(h\) 的后半部分合法。

倒序考虑 \(x_n,\cdots,x_1\),在考虑到 \(x_i\) 时,我们记录 \(mn=\min\limits_{i+1\leq j\leq n}h_j\) 和 \(r_{i+1}\),枚举 \(r_i=r_{i+1}-c\ (c\in\{0,1\})\),那么限制为 \(x_i=h_i-\min(h_i,mn,r_i)+1\)。若 \(x_i>1\),则可以固定 \(h_i=x_i+\min(mn,r_i)-1\);若 \(x_i=1\),则取 \(1\leq h_i\leq\min(mn,r_i)\) 都满足限制。

这里需要指出,我们始终令 \(h_i=x_i+\min(mn,r_i)-1\) 即可,后面的分析会解释原因。

不妨先代入 \(h_i\leq h_{i+1}+1\) 的限制:

\[x_i+\min(mn,r_{i+1}-c)-1\leq x_{i+1}+\min(mn,r_{i+1}) \]

这启发我们只需关心 \(mn\) 和 \(r_i\) 的相对大小关系。于是考虑记录 \(d=\max(mn-r_{i+1},0)\),那么限制变成:

\[x_i\leq x_{i+1}+1-[d>0]c \]

加入 \(h_i,r_i\) 后,新的 \(d'=\max(\min(mn,h_i)-r_i,0)\)。若 \(mn\leq r_i\) 则 \(d'=0\);否则 \(h_i=x_i+r_i-1\),\(d'=\max(\min(mn-r_i,x_i-1),0)=\max(\min(d-c,x_i-1),0)\)。综合一下可以得到 \(d'=\max(\min(d-c,x_i-1),0)\)。

观察到 \(x_i=1\) 时后续 \(d\) 都会变成 \(0\),这就说明了我们始终取 \(h_i=x_i+r_i-1\) 是正确的。

现在我们扫的过程中只需记录 \(d\) 和 \(x_{i+1}\) 并枚举 \(c\)。但是不同的 \(x\) 序列还是可能被不同的 \(c\) 重复计入贡献。

考虑到我们更希望 \(d\) 尽快降到 \(0\),可以考虑贪心,每次尽可能令 \(c=1\)。那么只有在 \(d>0\land x_i=x_{i+1}+1\) 时我们必须取 \(c=0\)。设贪心过程中有 \(u\) 次强制选 \(0\),我们指出,一组 \(x\) 合法当且仅当不存在 \(x_i>x_{i+1}+1\) 且 \(u\leq n-x_n\)。

证明

先证必要性。不难发现贪心策略每一步得到的 \(d\),一定不大于任意策略对应步得到的 \(d\),因此贪心策略强制选 \(c=0\) 的位置,任意策略也都必然强制选 \(c=0\),于是要有 \(u\leq n-x_n\)。

再证充分性。考虑贪心选择了 \(n-1-u\) 次 \(c=1\),我们直接保留前 \(t-1\) 个 \(c=1\),剩下的改成 \(c=0\)。那么选择完前 \(t-1\) 个 \(c=1\) 后 \(d\) 就变成 \(0\) 了,只剩下 \(x_i\leq x_{i+1}-1\) 的条件,显然合法。\(\Box\)

至此我们可以设计 DP 了。考虑到 \(x_i\) 时,令 \(dp_{v,d,t}\) 表示 \(x_{i+1}=v\),贪心时维护的差值为 \(d\),\(x_n+u=t\) 时的方案数。

初始时枚举 \(1\leq x_n\leq a_n\),令 \(dp_{x_n,x_n-1,x_n}=1\)。

转移时枚举 \(x_i\leq a_i\),分讨:

  • \(x_i\leq v\):\(dp_{v,d,t}\to dp_{x_i,d',t}\),其中 \(d'=\max(\min(d-1,x_i-1),0)\)。
  • \(x_i=v+1\):\(dp_{v,d,t}\to dp_{x_i,\min(d,v),t+[d>0]}\)。

第一条转移可以固定 \(x_i,d,t\) 对 \(dp_{v,d,t}\) 做后缀和。时间复杂度为 \(\mathcal{O}(n^4)\)。

主要代码
int n, a[MAXN];
mint dp[2][MAXN][MAXN][MAXN], suf[MAXN];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	cin >> n;
	for (int i = 1; i <= n; ++i) cin >> a[i];

	for (int v = 1; v <= a[n]; ++v) dp[n & 1][v][v - 1][v] = 1;
	for (int i = n - 1; i; --i) {
		int cur = i + 1 & 1, nxt = cur ^ 1;
		for (int x = 1; x <= n; ++x) {
			for (int d = 0; d < n; ++d) {
				fill(dp[nxt][x][d] + 1, dp[nxt][x][d] + n + 1, 0);
			}
		}
		for (int d = 0; d < n; ++d) {
			for (int t = 1; t <= n; ++t) {
				suf[n + 1] = 0;
				for (int x = n; x; --x) suf[x] = suf[x + 1] + dp[cur][x][d][t];
				for (int x = 1; x <= a[i]; ++x) {
					int nd = max(min(d - 1, x - 1), 0);
					dp[nxt][x][nd][t] += suf[x];
					if (x > 1 && t + (d > 0) <= n) dp[nxt][x][min(d, x - 1)][t + (d > 0)] += dp[cur][x - 1][d][t];
				}
			}
		}
	}

	mint ans = 0;
	for (int x = 1; x <= a[1]; ++x) {
		for (int d = 0; d < n; ++d) {
			for (int t = 1; t <= n; ++t) {
				ans += dp[1][x][d][t];
			}
		}
	}
	cout << ans;
	return 0;
}
posted @ 2026-10-11 11:01  P2441M  阅读(11)  评论(0)    收藏  举报