2026.8 做题记录
2026.8.20
P16365 [OOI 2026] Tasks from Sasha
那么每个关键点都相当于是选择一个集合 \(S\),有:
- \(S \subseteq T(u)\)。系数为 \(1\)。
- \(S=\emptyset\)。系数为 \(|son_u|-1\)。
- \(S\subseteq T(v)\)。系数为 \(-1\)。
要求任意两个关键点选择的集合不交,求系数乘积之和。考虑转化成每个点可以加入某个集合。
定义状态函数 \(f_{u,i}\) 为对于 \(u\) 子树中的点,可加入的在 \(fa_u\) 到 \(1\) 路径中的集合数量为 \(i\) 时的贡献和。那么:
- \(u\) 不是关键点。\(f_{u,i}=(i+1)\prod\limits_{v\in son_u}^{} f_{v,i}\)。
- \(u\) 是关键点。
- \(S\subseteq T(u)\)。\(f_{u,i-1}\gets (i+1)\prod\limits_{v\in son_u}^{} f_{v,i}\)。
- \(S = \emptyset\)。\(f_{u,i}\gets (|son_u|-1)(i+1)\prod\limits_{v\in son_u}^{} f_{v,i}\)。
- \(S\subseteq T(v)\)。\(f_{u,i} \gets -(i+1)\sum\limits_{v\in son_u}^{}\frac{f_{v,i+1}}{f_{v,i}}\prod\limits_{w\in son_u}^{}f_{w,i}\)。
答案为 \(f_{1,0}\)。复杂度 \(O(nk)\)。
考虑把虚树建出来。一个点 \(u\) 被保留到虚树中,当且仅当满足以下条件之一:
- \(u\) 是关键点。
- \(u\) 存在至少两个儿子是关键点。
- \(u\) 父亲是关键点。
对于被保留的点,相当于将它和它父亲之间所有没保留的点缩在一起。那么每个点有个 \(cnt_u\) 表示这个虚树上的点原来是由多少个点缩在一起的。
再考虑转移:
- \(u\) 不是关键点。
- \(u\) 子树中没有关键点(\(u\) 是一个非关键点叶子)。\(f_{u,i} = (i+1)^{cnt_u}\)。
- \(u\) 子树中有关键点。\(f_{u,i} = (i+1)^{cnt_u}\prod\limits_{v\in son_u}^{}f_{v,i}\)。
- \(u\) 是关键点。\(f_{u,i} = (i+2)^{cnt_u}\prod\limits_{v\in son_u}^{}f_{v,i+1} + (|son_u|-1)(i+1)^{cnt_u} \prod \limits_{v\in son_u}^{}f_{v,i}-(i+1)^{cnt_u}\sum\limits_{v\in son_u}^{}\frac{f_{v,i+1}}{f_{v,i}}\prod\limits_{w\in son_u}^{}f_{w,i}\)。
但是这个虚树的大小仍然是 \(O(n)\) 的。因为真正的虚树并没有保留第三类点。
发现对于第三类点,其 \(f_{u,i}\) 是可以直接算得的,只跟 \(cnt_u\) 有关。记 \(s_u\) 为 \(son_u\) 中属于第三类点的 \(v\) 对应 \(cnt_v\) 之和。那么由于 \(\sum cnt_v = s_u\),所以 \(cnt_v\) 的种类数是 \(O(\sqrt{s_v})\) 的。那么转移 \(u\) 时直接枚举这 \(O(\sqrt{s_v})\) 中 \(cnt\),就可以在 \(O(\sqrt{s_v}\log n)\) 的复杂度算出来了。
那么第三类点就可以不用来转移了,虚树大小时 \(O(k)\) 的。时间复杂度 \(O(k\sum \sqrt{s_{x}}\log n)\),其中 \(\sum s_x \le n\)。取 \(s_i = \frac{n}{k}\) 达到上界。复杂度即为 \(O(k\sqrt{nk}\log n)\)。预处理可以做到 \(O(k\sqrt{nk})\)。
注:转移中 \(|son_u|\) 始终是原树的 \(|son_u|\)。
CF1799G Count Voting
先按照 \(t\) 从小到大排序,那么 \(t\) 相同的在一个区间内。
定义状态函数 \(f_{i,x,y}\) 为对前 \(i\) 个团队的人来说,一共还差 \(x\) 张票,有 \(y\) 个人投给后面的人都方案数。记 \(s_i\) 为前 \(i\) 个团队的人一共差多少张票,\(cnt_i\) 为人数。有 \(cnt_i - y=s_i - x\)。也就是 \(y = cnt_i - s_i + x\)。
对于第 \(i\) 个团队,已知这里面的人一共差了 \(S\) 张票,且有 \(Cnt\) 个人。考虑枚举这 \(Cnt\) 个人有 \(a\) 个人投给前 \(i-1\) 个团队,获得了前 \(i-1\) 个团队中 \(b\) 个人的投票。那么有:
记第 \(i\) 个团队的人差的票为 \(c_1\sim c_k\),则 \(g_i = \binom{\sum\limits_{i=1}^{k}c_i}{c_1,c_2,\dots,c_k}\)。
化简一下,有:
答案为 \(f_{k,0}\),其中 \(k\) 为团队数量。时间复杂度 \(O(\sum n^2S_i)\),其中 \(S_i\) 为第 \(i\) 个团队差了多少张票。因为 \(\sum S_i = n\),所以复杂度 \(O(n^3)\)。
这个题也可以容斥,定义 \(f_{i,j}\) 为前 \(i\) 个人来说,钦定 \(j\) 个人投自己团队。就可以实现单步转移。复杂度 \(O(n^2)\)。
2026.8.21
P5189 [COCI 2009/2010 #5] ZUMA
定义状态函数 \(f_{l,r}\) 为如果将 \([l,r]\) 中的弹子删完,最小需要插入多少颗弹子。
那么 \([l,r]\) 要删完,相当于是找到若干个子区间 \([l_x,r_x]\),使得这些子区间先删完,再将剩下的删完。显然可以钦定剩下的都是同色的,因为如果不同色找到第一个变色点的位置后就可以变成两个子区间。
定义状态函数 \(g_{k,x,y}\) 为如果在 \([l,k]\) 中选了若干个子区间,且剩下的弹子颜色为 \(x\),有 \(y\) 个(和 \(K\) 取较小值后)的最小代价。则:
- 不选。\(g_{k,c_k,\min(y+1,K)}\gets g_{k-1,c_k,y}\)。
- 选。\(g_{k,x,y}\gets \min\limits_{k' = l}^{k}g_{k'-1,x,y}+f_{k',k}\)。
初始化 \(g_{l-1,*,0}=0\),最后 \(f_{l,r} = \min\limits_{x,y}^{}g_{r,x,y}+(K-y)\bmod K\)。
枚举 \(l\),顺着扫 \(r\) 时就可以维护 \(g_{r,*,*}\)。对于单个 \(l\) 的时间复杂度 \(O(n^3K)\)。总复杂度 \(O(n^4K)\)。
QOJ15521 XOR Again?
考虑划分的代价中二进制下第 \(x\) 位什么时候会是 \(1\)。显然应当满足存在一个划分区间 \([l,r]\),满足 \([l,r]\) 中有奇数个数二进制下第 \(x\) 位为 \(1\)。
考虑分成 \(i\) 组和分成 \(i-1\) 组的决策关系。
如果分成 \(i-1\) 组的最优决策不是合并分成 \(i\) 组的最优决策中某相邻两个区间,说明存在一个高位 \(x\),使得分成 \(i-1\) 组的最优决策的代价第 \(x\) 位为 \(0\),而无论分成 \(i\) 组的决策怎么合并都不能让这一位为 \(0\)。而又因为分成 \(i-1\) 组的最优决策中一定满足所有区间 \([l,r]\),使得这个区间中有偶数个第 \(x\) 位为 \(1\) 的数,且 \(i-1 \le n-1\)(即一定存在长度大于 \(1\) 的区间)。那么一定可以选择某个长度大于 \(1\) 的区间 \([l,r]\) 分成两部分,使得这 \(i\) 组的代价中第 \(x\) 位为 \(0\)。与最优策略矛盾。
那么维护分成 \(i-1\) 组的代价就只需要找到合并后代价最小的相邻区间了。
到着做。变成维护加入一个数后代价的最小值。
P10824 [EC Final 2020] Plants vs Zombies
先按照出现时间从小到大排序,时间相同的按照编号从小到大排序。
考虑二分第 \(i\) 个僵尸的死亡时间 \(T\):
- 对于地刺。已知行走的范围为 \((0, (T-t_i)V]\)。那么受到的伤害为 \(\sum\limits_{0 < p_x \le (T-t_i)V}^{}a_x\)。
- 对于豌豆。如果当前时间 \(T\) 小于前 \(i-1\) 个僵尸的最大死亡时间 \(T_0\),豌豆是不会攻击到这个僵尸的。否则会受到 \((T-T_0)KD +\delta D\) 的伤害。其中 \(\delta D\) 为前 \(i-1\) 个僵尸最后死亡的那个在 \(T_0\) 时错过的豌豆数量。注意 \(T_0 < t_i\) 的情况。
时间复杂度 \(O(n\log V\log n)\)。
QOJ12121 Golf
这里钦定第一个洞为 \(v_1\),第二个为 \(v_2\)。定义 \(f_{i}\) 为从 \(1\) 出发,走到 \(i\) 的概率。
先构造一条链 \(2 \to \dots \to k\)。让 \([1,k]\) 中的点选择性地连向 \(v_1\) 或 \(v_2\)(也可以不连,看作向 \(i+1\) 连重边)。发现如果点 \(x\) 连向 \(v_1\),会让 \(f_{v_1}\) 增加 \(\frac{2^{k-x}}{2^k}\)。这样可以把 \(f_{v_1}\) 的分子调成 \(a\),但无法改变分母。
考虑将某个点 \(x\) 连回 \(1\):分母变成 \(2^{k}-2^{k-x}\)。
那么分母也可以调了。找到最小的 \(k\),使得 \(2^k \ge a+b\)。先连 \(3\to 4\to 5\to \dots \to (3+k-1)\)。记 \(c = 2^k-a-b\)。相当于 \(1,2,3\) 分别要得到 \(a,b,c\) 这么多贡献了。
考虑维护 \(f_{1},f_2,f_3\) 还差多少。从低位往高位枚举,显然会恰好有两个数这一位是 \(1\),不妨设是 \(2,3\)。新加入一个点 \(t\),\(t\) 向 \(2,3\) 连边会有:
- \(f_{1}\gets f'_1\)。
- \(f_{2}\gets \frac{1}{2}f_t\)。
- \(f_{3}\gets f'_3 + \frac{1}{2}f_{t}\)。
那么 \(2,3\) 这一位就满足条件了。
具体地,维护 \(a,b,c\) 为当前差多少。若 \(b,c\) 是奇数,更新:\(a \gets \frac{a}{2},b\gets b, c\gets \frac{c-b}{2}\)。如果 \(b >c\) 交换 \(b,c\) 让小的不变就行了。
点数是 \(\log V\) 的。
CF1439D INOI Final Contests
最后有人的位置肯定是很多个区间。因为各自区间独立,所以只需要对每个区间都算一下再拼起来。
先不考虑计算贡献,只计算方案数。定义 \(f(n)\) 为 \(n\) 台电脑,\(n\) 个人坐满的方案数。对于最后一个人,设他的位置是 \(pos\),那么应该满足:
- \(b_n = L\),此时 \(a_n \le pos\)。
- \(b_n = R\),此时 \(a_n \ge pos\)。
共 \(n+1\) 种选择,然后就变成 \([1,pos-1]\) 和 \([pos+1,n]\) 两个子问题了。有:\(f(n) =(n+1)\sum\limits_{pos=1}^{n}f(pos-1)f(n-pos)\binom{(pos-1)+(n-pos)}{(pos-1)}\)。
简单的,既然我们枚举了每个人的 \(pos\),那么就可以维护每个人的贡献。即:
- \(b_n = L\),此时贡献为 \(pos - a_n\)。
- \(b_n = R\),此时贡献为 \(a_n - pos\)。
记 \(c(n,pos) = \sum\limits_{i=1}^{pos}(pos -i) + \sum\limits_{i=pos}^{n}(i-pos)\)。将贡献拆开,维护 \(f(n,0/1)\) 为 \(n\) 台电脑,\(n\) 个人坐满,且是否有一个人计算了贡献的方案数(乘上贡献和)。比如第 \(n\) 个人产生了贡献,就是:\(f(n,1)\gets \sum\limits_{pos=1}^{n}c(n,pos)f(pos-1,0)f(n-pos,0)\binom{(pos-1)+(n-pos)}{(pos-1)}\)。
最后将区间拼起来,定义 \(g(n,x,0/1)\) 为 \(n\) 台电脑,坐了 \(x\) 个人,且是否有一个人计算了贡献的方案数(乘上贡献和)。转移是简单的,枚举最后一个区间的长度再前缀和即可。最后答案为 \(g(n,m,1)\)。时间复杂度 \(O(n^3)\)。
2026.8.24
CF1784D Wooden Spoon
考虑直接算方案数。
注意到对于一棵满二叉树,最后的赢家一定是最小值。
枚举得到木勺奖的是 \(x\)。那么有:
- 第一轮赢他的人 \(y\) 满足 \(y < x\)。
- 第二轮赢 \(y\) 的人满足 \(z < y\),且 \(z\) 子树中有 \(2 ^ 1 - 1\) 个比 \(z\) 大的人。
- 第三轮赢 \(z\) 的人满足 \(w < z\),且 \(w\) 子树中有 \(2^{2}-1\) 个比 \(w\) 大的人。
- ……
- 第 \(n\) 轮赢上一轮赢家 \(k\) 的人满足 \(1 < k\),且 \(1\) 子树中有 \(2^{n-1}-1\) 个比 \(1\) 大的人。
设倒数第 \(i\) 轮的赢家为 \(p_i\)。则 \(1 = p_1 < p_2 <\dots < p_{n-1}<p_n < x\)。对于 \(p_i\),此时可选的人数为:\(2^n- 2^{n-i}-p_i\)。那么总的方案数为:
- \(2^{n}\prod\limits_{i=1}^{n}2^{n-i}(2^n-2^{n-i}-p_i)^{\underline{2^{n-i}-1}}\)。
定义状态函数 \(f_{i,j}\) 为 \(p_j = i\) 时,\(p_{1\sim j}\) 的方案数乘积和。则:\(f_{i,j}=2^{n-i}(2^n-2^{n-i}-p_i)^{\underline{2^{n-i}-1}}\times \sum\limits_{k=1}^{i-1}f_{k,j-1}\)。最后对于 \(x\),答案就是 \(2^n\sum\limits_{y<x}^{}f_{y,n}\)。
前缀和做到 \(O(n2^n)\)。
P9140 [THUPC 2023 初赛] 背包
记 \(\frac{c_i}{v_i}\) 最大的为 \(\frac{c_0}{v_0}\)。那么相当于能选就选,最后再退回几个选别的。对于点 \(x\),如果再选一个 \(i\),贡献为 \(c_i - c_0 \lfloor\frac{x+v_i}{v_0}\rfloor\),转移到的点为 \((x + v_i)\bmod v_0\)。这是个同余最长路。
转两圈跑即可。时间复杂度 \(O(n\max v_i + q)\)。
P14994 异或最短路和
先求个 DFS 树,对于非树边 \((u,v)\),记它的权值为边权异或上 \(u\) 到 \(v\) 路径异或和。那么一条 \(s\) 到 \(t\) 的路径权值就可以由 \(s\) 到 \(t\) 路径边权异或和与任意非树边权值异或和表示。
把非树边的权值塞到线性基里,记 \(g(s,t)\) 为 \(s\) 到 \(t\) 路径边权异或和。那么就是求线性基中元素与 \(g(s,t)\) 的最小异或和了。
记线性基中二进制下第 \(i\) 位的向量为 \(b_i\)。定义 \(f(x)\) 为线性基中对 \(x\) 的最小异或和。那么有:\(f(x) = \bigoplus\limits_{i}^{}(x_{i}\times b_i)\)。注意到 \(f(x\oplus y) = f(x) \oplus f(y)\),因为:
这里 \(x_i\oplus y_i\) 和乘法能拆是因为 \(x_i,y_i\in \{0,1\}\)。
那么对 \(f(g(s,t))\),就可以先对每条边求 \(f(w_i)\),再求路径异或和了。
树上差分任意维护做到 \(O(n\log V + n\log n)\)。
P14256 平局(draw)
对局面维护状态数组 \(s\):
- \(s_i\) 为 \(<\) 表示 \(i\) 和 \(i+1\) 玩会剩下 \(i+1\)。
- \(s_i\) 为 \(=\) 表示二者平局。
- \(s_i\) 为 \(>\) 表示 \(i\) 和 \(i+1\) 玩会剩下 \(i\)。
考虑有效的操作 \(i,i+1,i+2\),应该是剩下 \(i,i+2\)。因为如果剩下的是 \(i+1,i+2\) 或 \(i,i+1\),不如以 \(i+1\) 或 \(i\) 为断点操作(这样不会让答案变小)。
对操作分类讨论:
- 操作 \(=\)。相当于直接删掉它,并将答案加 \(1\)。
- 操作 \(><\)。相当于直接删掉它们,并将答案加 \(1\)。
- 操作 \(<<\)。可以变成 \(>\),方式是将后两个合并。这里不将前两个合并是因为合并后并不是删去了中间那个数。
- 操作 \(>>\)。可以变成 \(<\)。
注意到真正贡献答案的只有 \(=\) 和 \(><\)。考虑直接贪心。
维护栈,考虑加入 \(s_i\) 后栈与答案的变化:
- \(s_i\) 是 \(=\)。答案加 \(1\),栈不变。
- \(s_i\) 是 \(<\)。
- 若栈顶是 \(>\),弹出栈顶并将答案加 \(1\)。
- 若栈顶是 \(<\),此时整个栈都是 \(<\)。可能贡献答案只有将两个 \(<\) 变成一个 \(>\)。则此时栈的大小一定为 \(1\)。将栈弹空并加入 \(>\)。
- 若栈为空,加入栈。
- \(s_i\) 是 \(>\)。直接加入栈。
最后栈会剩下一个 \(<\) 或若干个 \(>\)。此时每 \(3\) 个还能产生 \(1\) 的贡献。
则任意时刻,栈只会是以下情况的一种:
- \(\{\}\)。
- \(\{(<),>,>,\dots\}\)。
- \(\{<\}\)。
定义状态函数 \(f_{i,1/2/3,j,0/1,1/2/3}\) 为考虑完 \(s_{1\sim i}\),当前栈是第 \(1/2/3\) 种情况,且当栈为第 \(2\) 种情况时栈中有 \(j\) 个 \(>\),且当栈为第二种时栈底是否是 \(<\),第 \(i+1\) 个人是石头、剪刀或布的方案数。
时间复杂度 \(O(n^2)\)。
P7324 [WC2021] 表达式求值
定义 \(f(s)\) 为如果初始这 \(m\) 个序列大于等于某个特定值的下标集合为 \(s\)(不在 \(s\) 中表示小于这个特定值),操作完后得到的结果是大于等于这个特定值的方案数。
由于 \(m \le 10\),所以 \(s\) 一共 \(2^{10}\) 种。复杂度 \(O(2^{m}|S|)\)。
因为 \(x = \sum\limits_{}^{}[i \le x]\)。所以只需要枚举 \(i\),对于这 \(m\) 个数组的每一个下标 \(x\) 维护 \(s_x\) 表示满足 \(A_{j,x}\ge i\) 的 \(j\) 的集合。那么答案等于任意时刻 \(\sum\limits_{x=1}^{n} f(s_{x})\) 之和。
考虑每次修改存在 \(A_{j,x} = i\) 的下标 \(x\),对每个 \(x\) 维护上一次变化的时刻 \(lst_x\)。这样每个 \(s_x\) 最多被修改 \(m\) 次,总复杂度 \(O(nm + 2^m|S|)\)。
2026.8.25
AT_arc160_f [ARC160F] Count Sorted Arrays
一个排列 \(p\) 操作后有序等价于对任意 \(1 \le x \le n\),将 \(p_{i}\ge x\) 看成 \(1\);\(p_i < x\) 看成 \(0\) 后所有 \(0\) 都在 \(1\) 前面。
对于一个二进制数 \(s\),向所有满足 \(t\mid s = s \land |s-t|=1\) 的 \(t\) 连有向边。那么任意一条 \(s = 2^{n}-1\) 到 \(t = 0\) 的路径都唯一地表示了一个排列。
维护 \(g_{s}\) 为当前时刻 \(s\) 是否已经操作成 \(000\dots 0011\dots 11\) 的形式。那么这个时刻的答案就等价于从 \(s = 2^n-1\) 开始走,每次只能经过 \(g_{x} = 1\) 的点,最终走到 \(t = 0\) 的方案数。
先考虑维护 \(g_s\)。对于每个 \(s\),维护 \(c_s\) 为到当前时刻时 \(s\) 的形态。那么这个时间操作 \((a,b)\) 等价于对所有满足 \(c_{s,a}=1,c_{s,b}=0\) 的 \(c_{s}\) 交换 \(a,b\) 两个位置。只要某个时刻 \(c_s\) 满足 \(0\) 全在 \(1\) 前面,\(g_{s}\) 在之后就都是 \(1\) 了。
根据冒泡排序,这样一个 \(s\) 交换次数是 \(O(n^2)\) 的(因为每次交换都是有效的)。那么直接做就是 \(O(n^32^n)\)。
再考虑维护方案数。相当于每次动态加入一个点,求 \(s=2^{n}-1\) 走到 \(t=0\) 的方案数。直接暴力更新所有需要更新的点,这样一个点 \(x\) 在某个满足 \(x \mid y = y\) 的 \(g_y\) 变成 \(1\) 时都会更新一次,且单次转移给出边对应点是 \(O(n)\) 的。总共就是 \(O(n3^n)\)。
整体时间复杂度 \(O(m + n3^n+n^32^n)\)。
CF1615F LEGOndary Grandmaster
考虑先将奇数位的 \(01\) 反转。那么操作就是交换相邻的 \(01\) 了。
贪心显然是 \(s\) 的第 \(i\) 个和 \(t\) 的第 \(i\) 个 \(1\) 相匹配。
考虑把贡献拆到边上。那么一条边 \((i , i + 1)\) 就会贡献 \(|cnt_{1,i}-cnt_{2,i}|\) 次操作。因为无论是外面进来还是里面出去都要操作这条边。
枚举边 \((i,i+1)\),枚举 \(cnt_{1,i}-cnt_{2,i}=x\) 和 \(cnt_{1,i}=a\)。记 \(c_{1/2,i}\) 为前缀 \(?\) 的数量,\(s_{1/2,i}\) 为前缀 \(1\) 的数量。那么贡献为:
同理,因为最终 \(cnt_1 - cnt_2 = 0\),所以 \([i+1,n]\) 中 \(cnt_{1,i}-cnt_{2,i}=-x\)。有:
那么最后答案就是 \(\sum\limits_{i=1}^{n-1}\sum\limits_{x=-n}^{n}F(i,x)G(i,x)|x|\)。时间复杂度 \(O(n^2)\)。
2026.8.26
P10068 [CCO 2023] Line Town
将所有奇数位的 \(a_i\) 取反,操作变成可以交换相邻两个 \(a_i,a_{i+1}\),问最后再将奇数位的 \(a_i\) 取反后满足 \(a_i\) 单调不减的最小操作次数。
首先序列肯定形如 \(a_1,a_2,\dots,a_k,0,0,0,\dots, 0,a_{p},a_{p+1},\dots,a_{n}\)。
负数段:
- 偶数位置满足 \(a_i \le 0\);奇数位置满足 \(a_i \ge 0\)。
- 偶数位置升序,奇数位置降序。
- 对于偶数 \(i\),满足 \(a_i + a_{i+1}\le 0\);对于奇数 \(i\),满足 \(a_i + a_{i+1}\ge 0\)。
零段,无特殊要求。
正数段:
- 偶数位置满足 \(a_i \ge 0\);奇数位置满足 \(a_i \le 0\)。
- 偶数位置升序,奇数位置降序。
- 对于偶数 \(i\),满足 \(a_i + a_{i+1}\le 0\);对于奇数 \(i\),满足 \(a_i + a_{i+1}\ge 0\)。
对于正数段,我们不将奇数位取反而将偶数位取反,然后正数段由单调不减变成单调不增了。且等价于将所有 \(a_i > 0\) 取反。
将所有 \(a_i >0\) 取反后从小到大排序,维护 \(b_i = 0/1\) 表示这个位置的值是否是由一个 \(a_i > 0\) 的数取反得到的。那么等价于将 \(a_i < 0\) 的序列分成两个下标子序列,满足:
- 第一个下标子序列对应的 \(b\) 形如 \(101010\dots\)。
- 第二个下标子序列对应的 \(b\) 形如 \((1)01010\dots\)。
如果知道了原序列下标 \(i\) 最终要移动到 \(p_i\) 的位置,最小操作次数等于 \(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i-1}[p_j>p_i]\)。考虑 DP 的时候提前计算这些贡献。
定义状态函数 \(f_{i,0/1,0/1}\) 为考虑完前 \(i\) 个数,第一个下标子序列末尾为 \(0/1\),第二个下标子序列末尾为 \(0/1\) 的最小代价。记 \(id_i\) 为第 \(i\) 个数在原序列的下标。对 \(i\) 放的位置分情况讨论:
- \(i\) 放在第一个子序列。此时对于还没放的数(\([i+1,n]\) 和所有 \(a_i = 0\)),由于无论怎么放都满足 \(p_{x} > p_{id_i}\),所以等价于还没放的数中,原序列下标小于 \(id_i\) 的数量,记为 \(cnt\)。那么:\(f_{i,b_i,0/1}\gets f_{i-1,b_i\oplus 1,0/1}+cnt\)。
- \(i\) 放在第二个子序列。同理,由于剩下的数无论怎么放都满足 \(p_x < p_{id_i}\),所以等价于原序列下标大于 \(id_i\) 的数量,记为 \(cnt\)。那么:\(f_{i,0/1,b_i}\gets f_{i-1,0/1,b_i\oplus 1}+cnt\)。
对于剩下的那些 \(a_i = 0\),肯定是按照原序列下标从小到大来放。那么相互之间不会有逆序对贡献,而与 \(a_i\ne 0\) 的贡献又已经计算过了,所以不需要管。
树状数组维护做到 \(O(n\log n)\)。
但是有个小问题,就是 \(a_i\) 相同的时候不太好确定先后考虑顺序。比如样例的 \(-8\) 和 \(8\),通过上述方式转化成 \(-8,-8\)。它们的 \(b\) 分别是 \(1,0\)。后面跟着一个 \(-7\),\(b\) 是 \(1\)。此时如果排成 \(011\) 就计算成无解了。
发现如果排序成 \(1001\),交换第二个 \(0\) 和第二个 \(1\) 是等价的,因为它们不可能放在一个子序列里。则此时只会是 \(010101\dots\) 或 \(101010\dots\)。
第一个子序列肯定是按照 \(id\) 从小到大放的,第二个肯定是从大到小放。这样就可以直接枚举分界点了。
整体时间复杂度依旧 \(O(n\log n)\)。
QOJ13142 Cleaning Robots
定义状态函数 \(f_{u,0/1,0/1}\) 为考虑完 \(u\) 子树,且 \(u\) 是否和两个儿子连且如果 \(u\) 和不超过一个儿子连,是否必须要和父亲连的方案数。
分情况讨论:
-
\(u\) 和不超过一个儿子连。
\[f_{u,0,0}\gets \prod\limits_{v\in son_u}^{} f_{v,1,0} + \sum\limits_{v\in son_u}^{}\frac{f_{v,0,0/1}}{f_{v,1}}(\prod\limits_{w\in son_u}^{} (f_{w,1}))\\ f_{u,0,1}\gets \sum\limits_{v\in son_u}^{}f_{v,0,0/1}(\prod\limits_{w\in son_u\land w\ne v}^{}(f_{w,0,0}+f_{w,1,0})- \prod\limits_{w\in son_u\land w\ne v}^{}f_{w,1,0}) \] -
\(u\) 和两个儿子连。
\[f_{u,1}\gets \sum\limits_{x\in son_u}^{}\sum\limits_{y\in son_u \land x\ne y}^{}f_{x,0,0/1}f_{y,0,0/1}\prod\limits_{w\in son_u \land w\ne x\land w\ne y}^{}(f_{w,0,0}+f_{w,1}) \]
任意维护做到 \(O(n)\) 或 \(O(n\log V)\)。
P15093 [UOI 2025 II Stage] Odd Rows
定义状态函数 \(f_{i,j}\) 为前 \(i\) 列考虑完,现在有 \(j\) 行是奇数的可行性。
考虑 \(j\) 个奇数行,\(m-j\) 个偶数行,再给 \(x\) 个行奇偶反转可以得到多少个奇数行。那么就是 \(j+x-2a\),其中 \(x -m+j \le a \le \min(j,x)\)。
直接用 set 维护转移路径做到 \(O(nm\log m)\)。
P13925 [POKATT 2024] 联合猫国 / The Paw-litical Game
暴力地,定义 \(f_i\) 为考虑完前 \(i\) 个城市后剩余城市数量。那么 \(f_{i} = \min\limits_{j<i\land c(j+1,i)}^{} f_{j}+1\)。其中 \(c(l,r)\) 为判定 \([l,r]\) 是否可以合并成一个城市。
维护 \(g_{i,j}\) 表示从 \(i\) 开始往前合并,使得最后合并成 \(a_i + j\),此时的区间左端点。那么:\(g_{i,j}=g_{g_{i,j-1}-1,a_i +j - a_{g_{i,j-1}-1}-1}\)。由于 \(c(l,r) = 1\) 的区间数量是 \(O(n\log n)\) 的,所以暴力跑时间复杂度 \(O(n\log n)\)。
在跑的时候维护 \(f_i\) 就行了。时间复杂度 \(O(n\log n)\)。
P3269 [JLOI2016] 字符串覆盖
可以先对每个字符串找到它在 \(A\) 中出现的位置,记为 \(pos_{i,1\sim k_i}\)。记第 \(i\) 个字符串长度为 \(l_i\)。
问题相当于对每个 \(i\),选择一个 \(1 \le p_i \le k_i\),使得 \(|\bigcup\limits_{i=1}^{n}[pos_{i,p_i},pos_{i,p_i}+l_i-1]|\) 最小或最大。
最小值。先去掉包含。枚举 \(pos_{i,p_i}\) 的相对大小顺序,这部分 \(O(n!)\)。定义状态函数 \(f_{i,x}\) 为前 \(i\) 小的 \(pos_{i,p_i}\) 对应 \([pos_{i,p_i},pos_{i,p_i}+l_i-1]\) 的并右端点在 \(x\) 时并集大小的最小值。枚举 \(p_i\),使得 \(pos_{i,p_i}+l_i-1\ge x\),转移为:\(f_{i,pos_{i,p_i}+l_i-1}\gets \min\limits_{x \le pos_{i,p_i}+l_i-1}^{}f_{i-1,x} + \min(l_i,pos_{i,p_i}+l_i-1-x)\)。可以直接搞是因为:
- \(x <pos_{i,p_i}\)。显然是对的。
- \(pos_{i,p_i}\le x \le pos_{i,p_i}+l_i-1\)。因为去掉了包含,所以不可能存在 \(x\) 所在被覆盖连通块左端点在 \([pos_{i,p_i},pos_{i,p_i}+l_i-1]\) 的情况。那么也是对的。
这部分时间复杂度 \(O(Tn!n|A|)\)。
最大值。再加个枚举子集。这样在情况 \(2\) 时如果这个左端点在 \([pos_{i,p_i},pos_{i,p_i}+l_i-1]\),显然会在去掉覆盖这一段的子集计算到更大值。所以是对的。
这部分时间复杂度 \(O(Tn!n2^n|A|)\)。
整体时间复杂度 \(O(Tn|A| + Tn!n|A|+Tn!n2^n|A|)\)。
2026.8.27
AT_agc040_c [AGC040C] Neither AB nor BA
如果没有 \(C\)。
将所有奇数位的 \(A,B\) 反转后,操作变成每次可以删掉相邻两个不同的字符。
那么就只需要满足 \(cnt_A = cnt_B\) 了。
再考虑有 \(C\) 的情况。将 \(C\) 看成通配符。
奇数位的 \(C\) 不会变,记这 \(cnt_C\) 个 \(C\) 中有 \(x\) 个是 \(A\)。那么应该满足 \(cnt_A + x = cnt_B +cnt_C-x\),即 \(x = \frac{cnt_B + cnt_C-cnt_A}{2}=\frac{n}{2}-cnt_A\)。
枚举 \(cnt_A = a,cnt_B = b\)。那么 \(x = \frac{n}{2}-a\)。显然反转之前的字符串和反转之后的字符串是双射关系,那么方案数就是 \(\binom{n}{a}\binom{n-a}{b}[0 \le \frac{n}{2}-a \le n-a-b]\)。
则答案为:
记 \(f(k) = \sum\limits_{b=0}^{\frac{n}{2}}\binom{k}{b}\)。那么:
时间复杂度 \(O(n)\)。
QOJ9565 Birthday Gift
将奇数位 \(0,1\) 反转。答案为:\(\min\limits_{x=0}^{cnt_{2}}|(cnt_{0}+x)-(cnt_1 + cnt_2-x)|\)。时间复杂度 \(O(n)\)。
P10367 [PA 2024] Żarówki
如果图是二分图。将左部点状态反转后变成可以交换一条边上两个点的状态。记第 \(i\) 个联通块中有 \(x\) 个 \(0\) 和 \(y\) 个 \(1\),则方案数就是 \(\binom{x+y}{x}\)。
如果图不是二分图。对于一个奇环,一定存在相邻的同状态点。发现这个时候只要环上 \(0,1\) 数量的奇偶数性不变,就可以任意操作得到。也就是说,方案数为 \(2^{cnt-1}\),其中 \(cnt\) 为环大小。
最后把每个连通块的方案数乘起来就行了。复杂度 \(O(n+m)\)。
2026.8.28
P17197 [KOI 2026 #2] 删除局部最小值
先把以 \(n\) 为根的笛卡尔树建出来。
思考点 \(x\) 何时被删。首先它不可能在它子树中任意一个点被删之前被删,设子树中最晚被删的时间为 \(t\)。那么在 \(t+1\) 时刻由于左右比它小的数都删完了,所以一定会被删掉。
那么 \(x\) 被删的时间等价于它到子树中最深点的距离 \(+1\)。
对于区间查询。记 \(k = \text{lca}(l,r)\)。那么 \([l,r]\) 中的点在笛卡尔树上的体现就是 \(k\) 子树除去 \(l\) 的左子树和 \(r\) 的右子树。
如果不管 \(l\) 的左子树和 \(r\) 的右子树的影响,删除的点应该是 \(k\) 子树中满足点到它子树中最深点距离不超过 \(t-1\) 的点。
再考虑 \(l\) 的左子树和 \(r\) 的右子树的影响。显然它们分别影响的都是 \(l\) 到 \(k\) 的链一段前缀,\(r\) 到 \(k\) 的链一段前缀。那么分别倍增找到第一个点,使得这个点 \(x\) 子树中除去 \(l\) 的左子树或 \(r\) 的右子树后最深的点到它的距离大于 \(t-1\)。
注意倍增到 \(k\) 的时候要同时除去 \(l\) 的左子树和 \(r\) 的右子树,还要整体减去 \(l\) 的左子树和 \(r\) 的右子树的贡献。
时间复杂度 \(O((n+q)\log n)\)。
P17019 [ROI 2026 Day1] 泰莫利亚的调查
问题可以转化成求选不超过 \(j\) 条点不交的链,使得边权和最大。
先给树做一个长链剖分。
考虑反悔贪心维护。加入一条链,因为进行的长链剖分,所以这条链上所有点都还没被选过。因为是长链,所以链内部一定是最优的,唯一可以改变的只有链头 \(x\) 和 \(fa_{x}\) 之间的边。即将 \(fa_x\) 原本原本连的儿子 \(v\) 替换成 \(x\)。这样的贡献是 \(\max(0,-w_{v,fa_x} + w_{x,fa_x}) + val\),其中 \(val\) 为这条链的边权和。
相当于是维护上面式子的最大值。
可以直接维护 \(fa_{x}\) 相同的链加入的相对先后顺序。枚举 \(fa_x = u\),首先最先加入的一定是 \(u\) 对应的长链。
将 \(u\) 的儿子按照 \(w_{v,u}\) 从小到大排序,设这一次加入的儿子为 \(v\)。考虑下一次加入的儿子 \(v'\) 的贡献:
- \(v'\) 排在 \(v\) 前面。贡献为 \(val_{v'}\)。即 \(v'\) 所属链的边权和。
- \(v'\) 排在 \(v\) 后面。贡献为 \(val_{v'}+ w_{v',u}-w_{v,u}\)。
维护一下前缀 \(val_{v'}\) 最大值和后缀 \(val_{v'}+w_{v',u}\) 最大值即可。因为带单点修改(将已经选的点删掉),所以需要线段树。(实际上可以直接维护 \(val_{v'}\) 和 \(val_{v'}+w_{v',u}\) 的最大值,不难发现下一次加入的儿子一定是其中之一)。
那么可以维护出加入一条链后下一次可能加入的兄弟链编号与这些兄弟链的贡献。拿个优先队列维护贡献最大的那个即可。整体时间复杂度 \(O(n\log n)\)。
2026.8.31
P11491 [BalticOI 2023] Tycho
定义状态函数 \(f_{i}\) 为在 \(i\) 的时候停下来等的最小代价。那么此时 \(i\) 位置的时间一定是 \(t = kp\)。
对于转移,考虑枚举上一个等的位置 \(j\)。那么经过时间为 \(a_i - a_j\)。代价为 $ \lfloor\frac{a_i-a_j}{p}\rfloor \times d + \lceil\frac{a_i-a_j}{p}\rceil \times p-d\times [(a_i-a_j)\bmod p = 0]$。
那么就可以分情况转移了:
- \(a_i \bmod p < a_j \bmod p\)。$f_i \gets (f_{j}-\lfloor\frac{a_j}{p}\rfloor \times d -\lfloor\frac{a_j}{p}\rfloor \times p) + (\lfloor\frac{a_i}{p}\rfloor \times d + \lfloor\frac{a_i}{p}\rfloor\times p - d) $。
- \(a_i \bmod p = a_j \bmod p\)。\(f_{i}\gets (f_j -\lfloor\frac{a_j}{p}\rfloor\times d -\lfloor\frac{a_j}{p}\rfloor\times p) + (\lfloor\frac{a_i}{p}\rfloor\times d + \lfloor\frac{a_i}{p}\rfloor\times p-d)\)。
- \(a_i\bmod p > a_j\bmod p\)。\(f_{i}\gets (f_j -\lfloor\frac{a_j}{p}\rfloor\times d -\lfloor\frac{a_j}{p}\rfloor\times p) + (\lfloor\frac{a_i}{p}\rfloor\times d + \lfloor\frac{a_i}{p}\rfloor\times p+p)\)。
树状数组做到 \(O(n\log n)\)。
P3059 [USACO12NOV] Concurrently Balanced Strings G
先考虑判定一个区间是否为括号匹配。
将 \()\) 看成 \(-1\),\((\) 看成 \(1\)。那么区间 \([l,r]\) 是括号匹配,当且仅当:
- 对于 \(i\in [l,r]\),\(s_i - s_{l-1}\ge 0\)。
- \(s_r - s_{l-1}=0\)。
其中 \(s_i\) 是前缀和。条件等价于 \(\min\limits_{i=l}^{r}s_i = s_{l-1}\) 且 \(s_{r} = s_{l-1}\)。
枚举 \(l\),对每个字符串维护 \([L_i, R_i]\) 表示当 \(r\in [L_i,R_i]\) 时,\([l,r]\) 的最小值等于 \(s_{l-1}\)。给区间取个交。问题变成 \([L, R]\) 中有多少个 \(r\),使得对所有 \(i\),均满足第 \(i\) 串中 \(s_r = s_{l-1}\)。
差分一下变成 \([1,R]\) 的问题。直接维护 \(cnt\) 就行了。时间复杂度 \(O(nk\log n)\)。
QOJ7943 LIS on Grid
- 一个序列最长上升子序列不超过 \(k\) 等价于其可以划分成 \(k\) 个不下降子序列。
考虑对于一个 \(k\),如何判定是否可行。首先这 \(k\) 个不下降子序列最长是不超过 \(m+n-k\),构造是让第 \(i\) 条的起点为 \((n-k+i,1)\),终点为 \((i,m)\)。这样所有不下降子序列一共需要上升 \(k\times (n-k)\)。
因为是不下降子序列,所以不上升的位置实际上可以不是黑点,即只强制每个子序列上升时需要是黑点。对于每一列,它至少贡献 \(\max(0,a_i - k)\) 个上升的黑点。那么首先可以划分的必要条件就是 \(\sum\limits_{i=1}^{m}\max(0,a_i-k)\le k\times (n-k)\)。
再考虑构造证明充分性。对于前 \(j-1\) 列,维护 \(pos_{i}\) 为第 \(i\) 个不下降子序列的结尾对应行数。那么第 \(i\) 行还差最多 \(pos_i-i\) 次上升。先随便让 \(\min(a_i,k)\) 个不下降子序列结尾往右走一格,显然此时 \(pos\) 不变。
从小到大处理 \(i\),因为贪心是能给 \(i\) 小的就给 \(i\) 小的,记 \(s = \sum\limits_{x=1}^{j-1}\max(0,a_x - k)\)。那么 \(pos_1 = (n-k+1)-\min(s,n-k),pos_2 = (n-k+2)-\min(s-(n-k),n-k)\dots\)。一定是一个前缀都匹配完,然后有一个还在匹配,剩下都在 \(n-k+i\)。此时这样匹配能产生贡献的上界是 \(n\)。即当 \(a_j \le n\) 时都能填满。否则说明所有的 \(i\) 都有 \(pos_i = i\)。此时 \(\sum\limits_{x=1}^{j-1}\max(0,a_x-k) = k\times(n-k)\)。若 \(a_j > k\) 则与条件不符。
时间复杂度 \(O(nm)\)。
P5305 [GXOI/GZOI2019] 旧词
考虑分块,记块长为 \(B\)。
对每个块 \(i\),维护 \(f_{i,y}\) 为 \(\sum\limits_{x=L_i}^{R_i}\text{depth}(\text{lca}(x,y))^k\)。这个的话枚举一个块,再枚举 \(u\)。可以快速维护出 \(cnt_u\) 表示 \(u\) 子树中有多少个在 \([L_i,R_i]\) 中的点。那么对于 \(u\) 子树内所有 \(y\),\(\text{lca}(y,x) = u\) 的数量就等于 \(cnt_{u} - cnt_{bel_y}\),其中 \(bel_y\) 是一个满足 \(bel_y\in son_u\) 且 \(bel_y\) 是 \(y\) 祖先的点。贡献为 \(\text{depth}(u)^k \times (cnt_u - cnt_{bel_y})\)。那么枚举 \(u\) 之后对 \(u\) 子树执行:
- 子树内所有点加上 \(cnt_{u}\times \text{depth}(u)^k\)。
- 子树内所有点减去 \(cnt_{u}\times \text{depth}(fa_u)^k\)。
DFS 序上差分一下做到 \(O(\frac{n^2}{B}+n)\)。
对于散块,直接枚举都是可以的。如果 \(\text{lca}\) 用 \(O(\log n)\) 的求法当 \(B =\sqrt{ \frac{n}{\log n}}\) 时做到 \(O(n\sqrt{n\log n})\)。
要 \(O(1)\) 求 \(\text{lca}\)。复杂度 \(O(n\sqrt{n}+n\log n)\)。
CF193D Two Segments
枚举值域上一个区间,合法当且仅当这个值域区间在序列上是不超过两个连续段。
考虑扫描线,扫 \(r\) 维护每个 \(l\) 的值域区间 \([l,r]\) 在序列上的连续段数量。
加入一个 \(r\),记 \(pos_r\) 为满足 \(p_{pos_r}=r\) 的下标。记 \(x = p_{pos_r-1},y = p_{pos_r+1}\)。当 \(pos_r = 1\) 或 \(p_{pos_r-1}> r\) 时 \(x=0\);\(y\) 同理。分情况讨论:
- \(l \in [\max(x,y)+1,r]\)。此时 \(pos_r\) 左右都没有数。段数 \(+1\)。
- \(l\in [\min(x,y)+1,\max(x,y)]\)。此时 \(pos_r\) 和左边或右边成一个连续段。段数 \(+0\)。
- \(l\in [1,\min(x,y)]\)。此时 \(pos_r\) 连接左右连续段。段数 \(-1\)。
那么就是区间加,维护全局段数不超过 \(2\) 的数量。
由于任意时刻段数不小于 \(1\),所以直接维护最小值和次小值的数量就行了。
线段树做到 \(O(n\log n)\)。
QOJ5357 芒果冰加了空气
定义状态函数 \(f_{u,x}\) 为 \(u\) 子树,有 \(x\) 个点在 \(fa_{u}\) 之前被删的方案数。
先考虑维护 \(g_{u,x}\) 表示有 \(x\) 个点在 \(u\) 之前被删的方案数。初始化 \(g_{u,0}=1\)。合并一个儿子 \(v\):
- 枚举 \(v\) 有 \(y\) 个点在 \(u\) 之前被删。\(g_{u,x+y}\gets g'_{u,x}\times f_{v,y}\times \binom{x+y}{x}\)。
对于 \(f_{u,x}\),有 \(f_{u,x} = \sum\limits_{y\ge x-1}^{}g_{u,y}\)。
时间复杂度 \(O(n^2)\)。
CF2077E Another Folding Strip
考虑一次操作能给哪些位置 \(+1\)。
设从左往右分别是 \(p_{1\sim k}\)。不难发现 \(p_i \not\equiv p_j \pmod 2\)。
对于 \(f(b)\),考虑二分答案 \(c\) 为操作次数。定义状态函数 \(f_{i,j}\) 为前 \(i\) 个数满足条件后,有 \(j\) 次操作的结尾是 \(p_x\bmod 2=0\) 的可行性。那么:
- \(i\) 是偶数。\(f_{i,j}= f_{i,j-b_i}\)。
- \(i\) 是奇数。\(f_{i,j} =f_{i,j+b_i}\)。
最后只要存在 \(f_{|b|,j}=1\) 就合法。初始 \(f_{0,j}=1 (0\le j \le c)\)。
不难发现这个转移路径是 \(c\) 条链。那么为了让 \(0 \le j \le c\),显然需要保证对任意区间 \([l,r]\),均有 \(|\sum\limits_{i=l}^{r}b_i (-1)^i |\le c\)。
将奇数位取反,那么 \(f(b) = \max\limits_{1\le l\le r \le |b|}^{}|s_r -s_{l-1}|\),其中 \(s_i\) 为前缀和。则 \(f(b) = \max\limits_{i=l-1}^{r}s_i - \min\limits_{i=l-1}^{r} s_i\)。
单调栈做到 \(O(n)\)。
P11819 [PA 2019 Final] Floyd-Warshall
直接做。
先求个最短路,维护 \(h(i,k,j)=[dis_{i,k}+dis_{k,j}=dis_{i,j}]\)。这个可以先搞个最短路图,然后枚举 \(i,j\),用 bitset 维护所有的 \(k\)。记为 \(h_{i,j}\)。
考虑定义 \(f_{i,j}\) 为 \(dis'_{i,j}\) 是否等于 \(dis_{i,j}\)。首先初始化时就满足的先赋成 \(1\)。对于转移就是 \(f_{i,j} =\bigcup\limits_{k=1}^{n} (f_{i,k}\cap f_{k,j} \cap h(i,k,j))\)。维护 \(S_{i} = \{k|f_{i,k} = 1\},T_i = \{k|f_{k,i}=1\}\)。那么就是 \(f_{i,j} = [S_i\cap T_i \cap h_{i,j}\not= \empty]\)。
时间复杂度 \(O(\frac{n^3}{\omega} + n^2 + m)\)。
P15551 Get MiN? Get MeX! 加强版
考虑每次拆成 \(4\) 个均等的区间 \(A,B,C,D\)。
查询 \(f(A),f(A+B),f(A+B+C)\)。可以根据这三个值的大小关系得到 \(0\) 所在的区间(最坏情况下只能知道是 \(A+B\) 或 \(C+D\))。
最后长度特别小的时候用询问 \(2\)。这样由于递归到 \(A+B\) 时 \(f(A'+B')=f(A)\),所以实际上除了第一次以外都只需要查询 \(2\) 次。那么查询次数满足 \(T(n) = T(\lceil\frac{2n}{4}\rceil)+2 +[n=N]\)。这个是不超过 \(35\) 的。
时间复杂度 \(O(\log n)\)。

浙公网安备 33010602011771号