模拟赛
2026.9.22
自胡蹿
考虑最优策略是什么。
一定是选择一个区间 \([l,r]\),不断操作让 \([l,r]\) 变成一个长度不小于 \(k\) 的回文串。
那么直接对这个 DP。维护状态函数 \(f_{l,r} = c\) 表示将 \([l,r]\) 变成回文串需要的最小操作次数。
那么对于 \([l,r]\),有:
- \(s_{l}\ne s_r\)。显然不可能形成回文串。
- \(s_{l}=s_r\)。可以同时拓展或单独拓展一边并给另一边操作一次。\(f_{l,r}=\min(f_{l+1,r-1},f_{l+1,r}+1,f_{l,r-1}+1)\)。
最后枚举选择的区间 \([l,r]\),代价就是 \(f_{l,r}+\max(0,k-(f_{l,r}+r-l+1))\)。
时间复杂度 \(O(n^2)\)。
跳跃
CF704B。
先考虑 \(O(n^2)\) 怎么做。
将代价拆开,变成 \((x_i+c_i),(-x_i+b_i),(x_i+a_i),(-x_i+d_i)\)。
连续段 DP。定义状态函数 \(f_{i,j}\) 为插入值 \([1,i]\) 后形成 \(j\) 个连续段时,代价最小值。分情况讨论:
- \(i\ne s,i\ne e\)。可以合并两个连续段(插在中间),插在一个连续段末尾或开头,单独形成一个连续段。
- \(i=s\)。可以单独形成一个连续段,插在一个连续段开头(且此时这个连续段不能再在开头插数)。
- \(i=e\)。可以单独形成一个连续段,插在一个连续段末尾(且此时这个连续段不能再在末尾插数)。
最后答案就是 \(f_{n,1}\)。时间复杂度 \(O(n^2)\)。
记 \(C_i = (x_i+c_i),B_i=(-x_i+b_i),A_i=(x_i+a_i),D_i = (-x_i+d_i)\)。
合并两个连续段代价是 \(A_i+ C_i\),插在末尾或开头是 \(A_i+D_i\) 或 \(B_i+C_i\),单独形成一个段是 \(C_i+D_i\)。
记 \(\alpha_i = B_i-A_i,\beta_i = D_i-C_i\)。那么就相当于先选 \((A_i+C_i)\),然后可以通过 \(\alpha_i,\beta_i\) 来变成其它情况。
这样每次加入一个 \(i\) 就可以考虑改变之前某个点的状态来插入。用小根堆维护最小值,复杂度 \(O(n\log n)\)。
当然连续段 DP 的第二维开小一点也可以过。
套娃
QOJ9865。
首先可以发现如果区间 \([l,r]\) 能全部合并在一起,那么任意一个 \([L,R]\subseteq [l,r]\) 也能全部合并在一起;同理如果 \([l,r]\) 不能合并在一起,那么任意一个 \([l,r]\subseteq [L,R]\) 也不能全部合并在一起。
想到维护极长可以合并在一起的区间。记 \(f_{l}\) 为最大的 \(r\),使得 \([l,r]\) 能够合并在一起。最后答案就等于从 \(x=1\) 开始,每次将 \(ans\) 加上 \(f_{x}-x\) 并将 \(x\) 跳到 \(f_x+1\)。
这个过程显然可以和 \(f_{l}\) 一起维护。
现在加入 \(a_r\),将 \([l, r-1]\) 划分成若干个极小的可能与之后某些数合并的区间。不妨设这些区间的值域分别是 \([L_1,R_1],[L_2,R_2],\dots,[L_k,R_k]\)。满足对于所有 \(1 \le i < k\),均有 \(R_i < L_{i+1}\) 或 \(L_i > R_{i+1}\)。
可以将它们的大小关系看成折线,\(R_i < L_{i+1}\) 看作向右上折;\(L_i > R_{i+1}\) 看作向右下。现在相当于加入一个点 \(a_r\),要求将这个折线从右往左合并的过程中不能出现值域区间相交的情况。
不妨设加入 \(a_r\) 后这个折线是向右下折的。找到前面第一个向右上折的点(\(R_{p}<L_{p+1}\)),当 \([p+1,k]\) 合并起来再和 \(a_r\) 合并后的值域区间与 \([L_p,R_p]\) 有交时,我们就不能直接把 \(a_r\) 加在后面。而是应该把 \([p,k]\) 合并起来,然后再尝试加入 \(a_r\)(因为 \([p+1,k]\) 永远都不可能独立得和后面某些数合并了)。
那么只需要维护每个点前面第一个折线方向不同的点编号。这个是简单的。
合并两个段段数会减少 \(1\),最多合并 \(n\) 次。所以复杂度 \(O(n)\)。
导览图
QOJ9805。
记第一棵树点集为 \(T_1\),第二棵为 \(T_2\)。
先考虑对一棵树计数。
注意到对于一条非树边 \((u,v)\),当其满足以下条件时是合法的:
- \((u,v)\) 不是横插边。
- 设 \(u\) 是 \(v\) 的祖先(不是则交换 \(u,v\))。记 \(w\) 为同时是 \(u\) 的儿子和 \(v\) 的祖先的那个点,则 \(w < v\)。因为当 \(w > v\) 时 \(u\) 会先走 \(v\),那么 \((u,w)\) 这条树边就不可能走到了。
那么对于一个树 \(T\),它的方案数就是 \(2^{\sum\limits_{u\ne root}^{}\sum\limits_{v\in subtree(u)}^{}[u < v]}\)。
再考虑求解原问题。先随便给 \(T_1\) 定一个根 \(root_1\),给 \(T_2\) 定一个根 \(root_2\)。
枚举连的这条边 \((u,v)\)(\(u\in T_1,v\in T_2\))。分情况讨论:
- \(x\in T_1\) 且 \(x\) 不在 \(u\) 到 \(root_1\) 路径上。此时 \(\sum\limits_{y\in subtree(x)}^{}[y>x]\) 不变。
- \(x\in T_1\) 且 \(x\) 在 \(u\) 到 \(root_1\) 路径上。当 \(x\ne root_1\) 时新的值等于原来的值加上 \(\sum\limits_{y\in T_2}^{}[y>x]\)。
- \(x\in T_2\)。此时 \(\sum\limits_{y\in subtree(x)}^{}[y>x]\) 就相当于以 \(v\) 为根时的值。
发现所有点实际上都只和自己所在的树有关。记 \(f(x)\) 为 \(u=x\) 时 \(T_1\) 中所有点贡献和,\(g(x)\) 为 \(v=x\) 时 \(T_2\) 中所有点贡献和。那么答案等于 \((\sum\limits_{u\in T_1}^{}f(u))\times (\sum\limits_{v\in T_2}^{}g(v))\)。
对于 \(f(u)\)。记 \(val = 2^{\sum\limits_{u\ne root}^{}\sum\limits_{v\in subtree(u)}^{}[u < v]}\),则 \(f(u) = val \times 2^{\sum\limits_{x\in P(u,root)\land x\ne root}^{}\sum\limits_{y\in T_2}^{}[y>x]}\)。对每个点 \(x\) 维护 \(c_x = 2^{\sum\limits_{y\in T_2}^{}[y>x]}\) 后就是点到根的 \(c\) 乘积。而 \(val\) 相当于是 \(O(n)\) 次查询子树在某个值域中点的数量。主席树维护即可。复杂度 \(O(n\log n)\)。
对于 \(g(u)\)。是一个换根的问题。假设现在已知 \(g(u)\),枚举一个 \(u\) 的儿子 \(v\),要求 \(g(v)\)。发现子树变化的点只有 \(u,v\) 两个点。变化前后的值也都形如查询子树在某个值域中点的数量,主席树维护。复杂度 \(O(n\log n)\)。
\(|T_1|\) 或 \(|T_2|\) 等于 \(1\) 时也可以不连边,这个方案数是简单的。
那么整体时间复杂度就是 \(O(n\log n)\) 的。
2026.9.23
游戏
把边转到点上,再做从下往上的差分。
那么将一条到根的链异或上 \(1\) 等价于单点修改。
每次操作只能把一个 \(1\) 变成 \(0\),终止局面为全 \(0\)。那么就只需要看有多少个 \(1\) 了。
不难发现,这个差分值实际上就是一个点所有边边权的异或和。那么一次修改只会影响 \(2\) 个点。
时间复杂度 \(O(n)\)。
小伙伴
把圆上 \(A\) 相同的点连边。得到 \(n\) 条弦。
对于任意两条弦,分情况讨论:
- 相交。由于最后弦是不交的,所以一定有某次交换被多算了一次。
- 不相交。显然可以保证任意时刻它们的关系都是不交的。
记 \(f(i)\) 为第 \(i\) 条弦的最小代价,那么答案就是 \(\sum f(i)\) 减去有交的弦对数。
记 \(L_i\) 为 \(A_x = i\) 中 \(x\) 较小值,\(R_i\) 为较大值。则答案等于 \(\sum\limits_{i=1}^{n}\min(R_i-L_i-1,L_i+2n-R_i-1)-\sum\limits_{i=1}^{n}\sum\limits_{j=i+1}^{n}[[L_i,R_i] 与 [L_j,R_j] 有交且不是包含关系]\)。
时间复杂度 \(O(n\log n)\)。
奇怪的树
考虑线段树分治。
那么 \(1\) 操作会变成 \(O(q)\) 个时间点,\(2\) 操作会变成 \(O((n+q)\log n)\) 个时间段。
因为信息不好合并,所以尝试把每个 \(1\) 操作都往这个时间点在线段树上的所有祖先中放一个。这样 \(1\) 操作是 \(O(q\log n)\) 个的。
问题变成,给定 \(k_i\) 个 \(1\) 操作的 \(u\) 和 \(s_i\) 个奇怪的点 \(v\),需要快速求出对每个点的贡献。其中 \(\sum k_i+s_i=O((n+q)\log n)\)。
建虚树直接跑一遍 DFS 即可。单次复杂度 \(O((k_i+s_i)\log(k_i+s_i))\)。整体复杂度就是 \(O((n+q)\log^2 n)\)。
但注意到复杂度瓶颈只在于给这 \(k_i+s_i\) 按照 dfn 序排序(排好后用单调栈和 \(O(1)\) 的 \(\text{lca}\) 建树),直接提前排序,然后按照 dfn 序插入那些操作即可。时间复杂度 \(O((n+q)\log n)\)。
三元组计数
对于一个边双,任意选择 \(3\) 个点当作 \(u,v,w\) 都是合法的。记点双大小为 \(s\),则方案数为 \(s^{\underline{3}}\)。
对于 \(u,v,w\) 不在一个边双的情况,将树上的边双缩一起之后等价于给定一棵树,每个点有个 \(cnt_{x}\),对所有合法的 \(u,v,w\) 求 \(cnt_u \times cnt_v \times cnt_w\) 之和。
这个容斥做。对于一个 \(w\),它合法的方案数就是 \((n-1)^2 -\sum\limits_{v\in son_w}^{}(siz_v)^2 - (n - siz_w)^2\)。对于这个缩完的数也可以这么维护。
用旅行的方式维护并查集来缩边双就行了。时间复杂度 \(O(n\alpha(n))\)。

浙公网安备 33010602011771号