Loading

P9746 「KDOI-06-S」合并序列 解题报告

题意:有一个数组,如果一个区间 \([l, r]\) 满足 \(\exists k \in (l, r), a_l \oplus a_r = \oplus a_k\),那么可以将这个区间压缩成一个数 \(\bigoplus_{l \le i \le r} a_i\)

我们将 \(\bigoplus_{l \le i \le r} a_i\) 记作 \(S(l, r)\)

\(1\leq T\leq20\)\(1\leq n\leq500\)\(0\leq a_i<512\)

测试点编号 \(n\) \(\sum n\leq\) \(a_i<\)
\(1\) \(=1\) \(20\) \(512\)
\(2\) \(=2\) \(40\) \(512\)
\(3\) \(=3\) \(60\) \(512\)
\(4\) \(=4\) \(80\) \(512\)
\(5\) \(=5\) \(100\) \(512\)
\(6\sim7\) \(\leq40\) \(800\) \(512\)
\(8\sim9\) \(\leq70\) \(1~400\) \(512\)
\(10\sim11\) \(\leq130\) \(2~600\) \(512\)
\(12\sim13\) \(\leq300\) \(6~000\) \(128\)
\(14\sim15\) \(\leq500\) \(3~000\) \(64\)
\(16\sim17\) \(\leq500\) \(3~000\) \(128\)
\(18\sim20\) \(\leq500\) \(10~000\) \(512\)

请对程序的常数以及效率给予充分的信任。

似乎特判一下 \(n \le 5\) 的数据,然后总司令可以拿到 \(35\)

首先就是对 \(n \in [1, 5]\) 进行特判,你可以拿到 \(25\) 分。

然后肯定是区间 DP,考虑设计状态 \(f(l, r)\) 代表 \([l, r]\) 是否能被合并成一个数。

image

然后,此时的 \(a'[L]\)\(a'[R]\) 都应该是原数组在 \([l, r]\) 上的一段前,后缀。然后 \(a'[K]\) 必然是一段区间 \([u, v]\) 使得 \(x < u \le v < y\)

也就是说,只要存在一种 \(l \le x < u \le v < y \le r\) 的方案,使得 \(S(l, x) \oplus S(u, v) \oplus S(y, r) = 0\)\(f(l, x)f(u, v)f(y, r) = 1\),那么 \(f(l, r) = 1\)

你可以暴力枚举 \(x, u, v, y\),这样是 \(\mathcal{O}(n^6)\) 的。可以获得和特判一样的分数。

优化到 \(\mathcal{O}(n^5)\) 是容易的:你只需要枚举 \(u, v, y\),并且在枚举 \(u\) 的同时,将 \([l, u - 1]\) 上的每个前缀和塞到桶里,然后枚举 \(y\) 的时候检查桶中是否有 \(S(u, v) \oplus S(y, r)\) 即可,有 \(35\) 了。

考虑继续优化。显然枚举 \(x, y\),然后判断 \([x + 1, y - 1]\) 内是否有合法区间是很有前途的。因此,我们新增状态 \(g(i, j, k)\) 代表区间 \([i, j]\) 内是否有异或和为 \(k\),且可以被合并的连续子段。

显然对于 \(g(l, r, k)\),我们可以大力枚举 \([l, r]\) 中的每一个区间 \([l', r']\),如果遇到 \(f(l', r') = 1\)\(S(l', r') = k\),那么 \(g(l, r, k) = 1\)。这样的话,\(g\) 数组的复杂度是 \(\mathcal{O}(n^4)\) 的。对于 \(f(l, r)\),我们枚举 \(x, y\),然后如果出现 \(f(l, x)f(y, r)g(x + 1, y - 1, S(l, x) \oplus S(y, r)) = 1\),那么 \(f(l, r) = 1\),这样总复杂度也是 \(\mathcal{O}(n^4)\) 的了。可以拿 \([45, 100]\),如果你对程序效率给予充分信任的话,可能会取到上界。

可不可以再少枚举一个数呢?如果我们只枚举 \(x\),那么就需要维护一个 \(h(j, k)\) 代表最大的 \(u\),使得存在 \(u \le v < y \le r = j\)\(S(u, v) \oplus S(y, r) = k\)\(f(u, v)f(y, r) = 1\)。考虑对 \(h\) 的计算:首先就是算一下 \(z(i, j)\) 代表找到最大的 \(u\) 使得存在 \(u \le v < i\),且 \(f(u, v) = 1\)。计算这个其实是容易的。计算完这个,再扫一遍即可计算 \(h(i, j)\)。再扫一遍即可计算 \(f(l, r)\)

输出方案时模仿转移,直接找到一种可能的转移就好。总时间 \(\mathcal{O}(n^3)\)

posted @ 2026-08-29 11:58  Trent900  阅读(8)  评论(0)    收藏  举报