9 月做题记录
26. 9. 1
P11491 [BalticOI 2023] Tycho
妈的傻逼题目,写红温了。警示录是一定要先写一个暴力 dp。
P3059 [USACO12NOV] Concurrently Balanced Strings G
先不考虑 bitset。考虑合法的括号序列条件是,记前缀和数组为 \(s_i\),那么一个区间 \([i,j]\) 合法的条件是 \([\min_{k=i}^j s_k = s_{i-1}][s_j = s_{i-1}]\),考虑首先对第一个东西做限制,我们对于每个 \(i\) 维护出来一个区间 \([L_i,R_i]\),那么可能的 \(j\) 只会取在这若干个区间的交集里。
然后考虑第二个限制,问区间 \([l,r]\) 有多少 \(s_i=k\),这个做完哈希,扫一遍就可以了,时间复杂度 \(O(nk \log n)\)。
QOJ7943 LIS on Grid
由 Dilworth 定理可以给最长上升子序列转化:
- 一个序列的最长上升子序列长度 \(\le k\) 等价于这个序列可以被划分为 \(k\) 个不升子序列。
对于网格图来说,更具体的转化是可以划分出 \(k\) 个从左下到右上的路径,由于每一行可以 \(\ge a_i\),多余的可以忽略掉,我们可以调整出这 \(k\) 条路径以 \((n-k+i,1)\) 为起点,\((i,m)\) 为终点。首先每一列都至少需要 \(k\) 个点来提供给路径,并且令 \(b_i = \max(0, a_i-k)\),那么 \(i\) 这一列至少需要 \(b_i\) 次上升,有不等式:
我们下面来证明这个上界是可以构造到的,贪心按链从上往下进行构造,对于第 \(i\) 条链尽可能在前面上升,这个构造显然是合法的,时间复杂度 \(O(nm)\)。
P5305 [GXOI/GZOI2019] 旧词
直接到根链带权加即可。
CF193D Two Segments
首先这个去重很奇怪,直接在值域上大力扫,然后维护合法左端点。然后做完了。
QOJ5357 芒果冰加了空气
考虑根节点被删除的时间,在这个时间之后每棵子树的删除时序独立,之前需要乘上一个多重集组合数,那么设 \(f_{u,i}\),每次后缀和然后卷起来就做完了。
CF1146H Satanic Panic
考虑怎么去刻画一个五边形的凸包,我们将其刻画为,从某个点出发,斜率一直递增,走了四条边。那么可以考虑设 \(f_{u,v,L,i}\) 代表从 \(u\) 到 \(v\),走了 \(i\) 条边,上一条边是 \(L \to v\) 的方案数。这样转移是 \(O(n^4)\) 的而,考虑优化一下,发现其实我们大可以直接把所有边按斜率排序,然后直接转移,设 \(f_{u,v,i}\),每次的边设为 \(v \to w\),那么直接转移就是对了,时间复杂度 \(O(n^3)\)。
P5540 [BalkanOI 2011] timeismoney
我们考虑给所有合法的方案,以 \((\sum a_i, \sum b_i)\) 看作一个点维护出来下凸包,我们首先求出这个凸包的两端,也就是和 \(x,y\) 轴距离最近的点,记作 \(P,Q\),那么考虑去凸包上二分 \(P \to Q\) 的斜率,考虑去找到刚好切到直线,并且截距最小的点 \(M\),那么可以把问题分为 \(P \to M,M \to Q\) 分别递归下去。
现在的问题是如何去找这个 \(M\),记斜率为 \(k\),截距为 \(y_0\),那么对于 \(M\) 就有 $\sum b_i -k\sum a_i $ 最小,那么我们直接在算生成树的时候给边权减一下算即可。
由熟知的结论,整数凸包的大小为 \(O(V^{2/3})\),那么本题复杂度就是 \(O((nV)^{2/3} (m +V))\)。
CF2077E Another Folding Strip
考虑先对这个操作做一些分析之类的,考虑一次染色可以染色的集合 \(S\) 有什么特征,首先我们猜测合法的条件是 \(S\) 中相邻两个点之间的格子数量都必须是偶数。满足这个显然有合法构造,否则显然没有合法性构造。
现在考虑怎么求 \(f(a_1a_{2}...a_n)\),限制是偶数位置和奇数位置必须交错选,这个可以看作是偶数位置和奇数位置进行抵消。我们考虑把偶数位置看作在折线图上走 \((1,a_i)\),否则走 \((1,-a_i)\),那么我们考虑一个答案 \(k\) 需要满足的必要条件:我们从折线上任意一点 \(P\) 出发,走到任意一点 \(Q\),走过的高度差 \(|\Delta h| \le k\)。
这个必要性是显然的,因为从 \(P \to Q\) 至少需要 \(\Delta h\) 个独立的 \(S\) 来把所有的多出来的偶数 / 奇数位置放进去。考虑充分性,这个明显有合法性构造。考虑答案 \(k\) 能取到的最小值显然就是最高点和最低点的高度差,对 \(a_i(-1)^i\) 数组做前缀和得到 \(s_i\) 数组,\(k\) 就形如 \(\max s_i - \min s_i\)。最后求所有子区间的贡献直接单调栈容易做到线性。
CF1787I Treasure Hunt
首先如果 \(q \in [s,t)\),那么把 \(q\) 调整到 \(t\) 一定不劣,那么可以直接把两个贡献给拆开算。
首先考虑前缀和最大值一项怎么算,直接大力分治,对左边维护起点到中点的和 \(s_L\),以及左侧起点本身的答案 \(w_L\),同理维护中点到右侧点随便选的权值前缀最大值 \(w_R\),那么一对 \(L,R\) 的答案就是 \(\max(w_L, s_L + w_R)\),遍历 \(L\),维护 \(\max(w_L - s_L,w_R)\),\(w_L - s_L\) 显然会随着 \(L\) 减小单增,\(w_R\) 也单调,那么直接扫就是对的。
接下来考虑最大子段和一项怎么算,我们考虑讨论最大子段和的状态:
- 最大子段和跨过 \(mid\):我们维护 \(w_L,w_R\) 代表从 \(mid\) 出发,向左,向右走的最大前缀和,那么这一部分的贡献是 \(w_L + w_R\)。
- 最大子段和位于 \(mid\) 左侧或者右侧:设 \(v_L,v_R\) 代表从 \(mid\) 出发向左,向右的最大子段和,这一部分的贡献是 \(v_L,v_R\)。
那么我们要求的就是 \(\max(w_L + w_R, v_L, v_R)\),首先我们枚举 \(L\),考虑首先讨论 \(v_L\) 和其他两项的偏序。首先 \(v_L\) 对 \(v_R\) 的偏序可以直接双指针,然后 \(v_L\) 对 \(w_L + w_R\) 的偏序可以看作是 \(v_L - w_L\) 对 \(w_R\) 的偏序。考虑 \(v_L - w_L\) 是什么,这个随着 \(L\) 减小显然单调不降。最后考虑 \(w_L+w_R\) 对 \(v_R\) 的偏序,也就是 \(w_L\) 对 \(v_R - w_R\) 的偏序,这个也可以指针。
那么做完了,时间复杂度 \(O(n \log n)\),这不就是一坨吗。
26. 9. 2
P14880 [ICPC 2019 Yokohama R] Halting Problem
什么傻逼一坨。考虑连边 \(i \to e_i\),每次更新状态,显然一个 \(a_i\) 的判定不会触发两次,那么就变成了 \(O(n)\) 次的一个在线的问题,环和链分开讨论即可。
P12624 [ICPC 2025 NAC] Humans vs AI
直接大力分治就是对的吧,写个树状数组维护偏序可以做到 2log。
P14284 [ICPC 2025 WF] Delivery Service
有点意思。首先考虑建立扩展域并查集,那么这个时候有上下两排点,有若干个连通块,第 \(i\) 个连通块记作 \(S_i\)。那么答案是:
但是我们注意到,一个点最多只会存在于两个并查集中,也就是说后一个式子最多只会有 \(O(n)\) 个非零值。这个东西可以启发式合并,直接做就是 \(O(n \log n) \sim O(n \log^2 n)\) 的。
26. 9. 3
为啥难度顺序递减啊。
快速旋转(express)
首先我们把这个问题看作一个环,然后有一个指针在上面移动,每次可以向左或者向右,或者把指针右边的数给删掉。
那么显然有一个 75 分的 dp,直接设 \(f_{i,p}\) 代表考虑了所有 \(\ge i\) 的数,指针最后停在 \(p\) 的最小代价。考虑相邻层之间的转移,显然转移分为顺时针和逆时针。我们考虑顺时针,那么我们会发现转移是对一个区间做形如 \(f_i = -sum_j + g_j + k\) 的转移,这个东西显然可以单调队列快速维护,复杂度是树状数组的 \(O(n \log n)\)。
画布(canvas)
首先最垃圾的做法是维护出来左边到上面,左边到右边,右边到上面的删除时间,但是巨难写。考虑如何在网格图上刻画一个连通块,我们刻画断点,对一个 \(2 \times 2\) 的网格做分析,如果只有右侧一个格子 / 右侧两个格子 / 只有对角有格子就认为有一个连通块,这样是矩阵加,可以离线扫描线维护前 \(k\) 小值即可。
但是有更聪明的做法,直接大力点减边容斥,每个 \(1 \times 2\) 的矩阵贡献一个 \(1\),每个 \(2 \times 2\) 的矩阵贡献一个 \(-1\),算出来的值对 \(1\) 取最大值即可。时间复杂度 \(O(nk \log n)\)。
请记住平面图欧拉定理,\(|V|-|E|+|F|=2\),\(V,E,F\) 分别是顶点,边和面!!
分层编辑器(editor)
这个题好难啊。首先维护一个栈代表当前还没有被撤销,但是可能会被一次撤销掉的集合,那么这个栈从上向下肯定是优先级单调递减的。记优先级为 \(p_i\),如果存在 \(i<j,p_i > p_j\),那么一定会先删掉 \(j\) 再删掉 \(i\)。
那么我们每一次想要把一个优先级为 \(t\) 的数字给加进栈,我们先二分第一个满足 \(p_k < t\) 的位置 \(k\),那么栈中 \([k+1,tp]\) 的所有元素都不会删除,会删掉 \(k\),考虑直接从 \(k-1\) 时刻的栈继承,加入 \(t\) 会把 \([k+1,tp]\) 的元素全部偏序,所以倍增或者主席树可以简单维护,时间复杂度 \(O(n \log n)\)。
P16545 [EGOI 2026] 狐狸家族 / Fox Families
经过手玩,不难发现有结论:
- 如果一个区间包含于或被包含于一个连通块的并集,那么这个区间可以和这个连通块合并。
包含是平凡的,考虑被包含的情况。我们记这个区间为 \([l,r]\),找到连通块第一个左端点 \(\le l\) 的区间 \([l_0,r_0]\),以及第一个右端点 \(\ge r\) 的区间 \([l_1,r_1]\)。不平凡的情况显然只有 \(r_0 < r \wedge l_1 > l\)。
此时首先如果有区间包含于 \([l,r]\) 是平凡的,否则如果 \([l_0,r_0]\) 和 \([l_1,r_1]\) 想要连通则必须会有一个区间彻底包含 \([l,r]\),这个画画图就明白了,那么我们拿 set 直接维护每个连通块,加入完毕 check 相邻有交的区间是否能合并,时间复杂度 \(O(n \log n)\)。
26. 9. 4
CF547D Mike and Fish
考虑如果存在一个类矩形,即如果存在四个点 \((x_0,y_0),(x_0,y_1),(x_1,y_0),(x_1,y_1)\),我们可以把其对角染红色或蓝色,不影响最终的方案。对题目建图,每个点 \((x,y)\) 看作是左部点 \(x\) 和右部点 \(y\) 连边,那么题目就是给边红蓝染色,要求每个点的所有连边红蓝边相差 \(\le 1\)。
那么显而易见地,我们可以每次删掉一个环,剩下的图是森林,对于每棵树暴力遍历就可以求出方案。
草这个几把套路我见过几遍了,建立一个虚点给所有奇数点连边,那么每个点度数都是偶数,跑欧拉回路即可。
P15869 【MX-X26-T5】「Cfz Round 7」anybody can finds love (expect you)
首先判掉奇数度数的点,然后考虑对于每个点 \(u\),必然有 \(\text{deg}_u / 2\) 条出边和入边,那么我们需要把这些出边和入边两两配对,那么此时如果存在绝对众数显然无解。
但是这样强制匹配边可能不对,因为可能走重复边,走重复边会在一个环上面一直走。但是考虑说如果我们走出了环可以把这个环删掉,记作 \(R\),剩下的部分是归纳有解的。先对剩下的部分进行构造,然后考虑把这个环给拼上去。
由于原图是无向连通图,那么 \(R\) 和 \(G -R\) 一定有一个相交的顶点,在这个顶点我们交换环 \(G -R\) 和环 \(R\) 的出边或者入边即可,如果无论交换出边或者入边都不合法,我们把 \(R\) 的所有边取反即可,时间复杂度 \(O(n)\)。实际上没有这么麻烦。
P5332 [JSOI2019] 精准预测
我们看作是 \(s_{i,x}\) 这 \(O(nm)\) 个变量,限制分别是 \(s_{i+1,y} \subseteq s_{i,x}\),$ s_{i,y} \subseteq \neg s_{i,x} \(,\)s_{i+1,x} \subseteq s_{i,x}$。考虑 2-sat,把每个点拆成 \(0,1\) 两个点。直接做复杂度是 \(O(nT)\) 的。
我们考虑换一个视角,把 \(s_{i+1,x} \subseteq s_{i,x}\) 的 2-sat 连边看作骨架,骨架的连边应该是 \((i,x,0) \to (i+1,x,0), (i+1,x,1) \to (i,x,1)\)。我们发现其他两种连边的总个数是 \(O(m)\) 的,我们根据这 \(O(m)\) 个连边压缩中间的骨架,这样的点数就压缩到了 \(O(n+m)\)。
现在的问题变成了对每个点做可达性统计,注意到这张图是张 DAG,那么直接大力 bitset。但是考虑到空间开不下,考虑分块然后跑 bitset,时间复杂度 \(O\left(\dfrac{(n+m)^2}{\omega}\right)\)。
P11095 [ROI 2021] 旅行 (Day 2)
首先我们枚举 \(t_{\max}\),从小到大枚举来一条一条加边,然后动态维护最小生成树。考虑我们加入一条边 \((u,v)\):
- 如果 \(u,v\) 此前不连通,把它们合并。
- 否则找到当前以 \(1\) 为根的最小生成树上,\(u\) 和 \(v\) 的 LCA,记作 \(x\),我们把 \(u \to v\) 的所有点全部缩起来缩成一个新的边双。
考虑这么做有什么好处,好处是缩完之后 \(1\) 到 \(k\) 的最小值就是在树上的边权或点权最小值。每次缩点的时候我们都给 DFS 序区间做 chkmin,需要开两棵线段树分别维护权值和答案,那么时间复杂度 \(O(n \log n)\)。我觉得这个题好难啊,因为感觉没想过往这个方向去维护。
CF2196E2 Fuzzy Concatenation (Hard version)
首先第一步显然每次拼一个尽可能大的。我们考虑如何判断 \(T[l:r]\) 是否可以被表示,考虑有一个 \(O((r-l+1) \text{polylog}(n))\) 的做法:
- 首先枚举断点 \(p\),那么问题等价于存在 \(S\) 串的某个断点 \(p_0\),使得 \(T[l:p)\) 是 \(S[1:p_0)\) 的后缀,且 \(T(p:r]\) 是 \(S(p_0,|S|]\) 的前缀。把这个写成 LCP、LCS,建立 SA 后做二维数点。
那么我们考虑二分,二分代价是和区间长度成正比。我们首先考虑倍增,找到最大的 \(k\) 使得满足 \([i,i+2^k)\) 合法,找到之后我们在 \([2^k,2^{k+1})\) 里面重新二分。这样做的好处是不会二分到很长的区间,二分判断的复杂度均摊下来是 \(O(m \log^2 n)\) 的。
P16541 [EGOI 2026] 饼干 / Biscuits
首先考虑 dp,设 \(f_i\) 代表吃掉了最顶上的 \(i\) 个饼干的最大权值,那么有转移,\(f_i = \text{secmax}_{j<i}(f_j) + W_i\),考虑怎么把这个东西优化掉,考虑到 \(W_i\) 值域很小。我们记 \(G_{i,0/1}\) 代表前面 \(f_j\) 的最大,次大值。那么 \(i\) 这次转移做的事情是给 \(G_{i,1}\) 加上 \(W_i\),然后如果 \(G_{i,0} < G_{i,1}\),交换 \(G_{i,0},G_{i,1}\)。
考虑对这个过程动态 dp 维护,维护一个长度为 \(V\) 的分段函数,第 \(i\) 个数代表从左边传进来 \(G_{0},G_{1}\) 的差值为 \(i\),然后对这个东西复合即可,时间复杂度 \(O(nV\log n)\)。
P13345 [EGOI 2025] IMO
考虑两个人 \(x,y(x<y)\) 如何确定严格的偏序关系,当且仅当 \(x\) 没填的全部填成 \(0\),\(y\) 没填的全部填成 \(k\),然后 \(x\) 的总分数还仍然大于等于 \(y\) 时可以确定。写出来是 \(sum_x \ge sum_y + t_y \times k\)。
由于偏序具有传递性,所以我们只要能确定原排名下相邻两行的偏序就可以确定整张榜。首先考虑大力 dp,注意到每一行删除的一定是一段排序后的区间,那么设 \(f_{i,l,r}\) 代表考虑了 \(\le i\) 行,上一行删除了 \([l,r]\) 的最小删除数量。转移时我们枚举上一行的所有区间 \([l,r]\),算出来权值 \(s\),把三元组 \((s,l,r)\) 桶排序维护一个前缀 \(\min\) 即可,时间复杂度 \(O(nm^2)\)。
草,我们注意到,如果一个人前后两个人的分数差 \(d<k\),那么这个人必须全部公开。更进一步发现最多只有 \(\dfrac{d}{k}\) 个分数不公开,那么所有人公开的分数总个数是 \(O(m)\) 的。那么其实可以直接大力 dp,设 \(f_{i,j}\) 代表考虑排名 \(\ge i\) 的人,上界限制是 \(j\),dp 然后 bitset 优化可以做到 \(O\left( \dfrac{m^3k}{\omega} + n (m+\log n)\right)\) 的复杂度。
26. 9. 4
P6643 [CCO 2020] Mountains and Valleys
首先我们不难观察到,最多只会走一条非树边。走两条非树边的话一定会被 \(ans - diam\) 偏序,这里 \(diam\) 是直径长度。
记 \(P(u,v)\) 代表 \(u \to v\) 这条路径。我们朴素地考虑枚举起点 \(s\),终点 \(t\),非树边 \((u,v,w)\),不难发现贡献是:(此处 _lbw_ 讲了一个欧拉路径的建模,但是感觉好像没啥用?):
这个东西直接大力树剖讨论不难做到 1log,但是事实上可以做到线性,具体来说,我们考虑点分治。只处理 \((u,v)\) 路径跨过分治中心的非树边。对 \(u\) 维护 \(u \to rt\) 上每个点选择某个子树里面的点的最大次大,然后随便维护一些东西,维护一下前四大,略去,感觉是大粪。
为什么时间复杂度线性的?因为点分治到连通块大小 $ \le \dfrac{N}{3}$ 后就没用了,所以点分治只有 \(2\) 层,时间复杂度线性。
QOJ10706 红蓝最小生成树
首先如果 \(k\) 是定值可以大力 wqs 二分,我们考虑这个凸性是怎么来的,首先我们对蓝边和红边都跑一遍 MST,那么每次我们可以看作是选择一条红色边去把一条蓝色边给替代掉,并且提供一个增量的贡献。
也就是说,我们想要对每条红边 \(r_i\) 求出其匹配的蓝边 \(b_{p_i}\)。首先把 \(n-1\) 条红边和蓝边按权值升序排序。最暴力的求法是,我们找到编号极大的蓝边 \(b_k\),并且加入 \(b_{1\sim k}\) 后 \(r_{i}\) 左右顶点仍然不连通。
这个过程可以做整体二分,具体来说,我们的 \(\text{solve}(L,R,Q)\) 进行以下流程,记 \(M=(L+R)/2\)。
- 首先我们加入 \(b_{L \sim M}\),依次遍历 \(Q\) 中的所有红边,检查左右端点是否连通。连通的划分到 \(Q_l\),否则划分到 \(Q_r\)。那么 \(Q_l\) 显然是匹配位置 \(\le M\) 的红边。
- 加入 \(Q_l\) 的所有红边,加入 \([L,M]\) 的所有蓝边,进行递归 \(\text{solve}(M+1,R,Q_r)\),递归后撤销。
- 加入 \(Q_r\) 的所有红边,进行递归 \(\text{solve}(L,M,Q_l)\)。这里加入 \(Q_r\) 不会错,递归后撤销。
时间复杂度 \(O(n \log^2 n)\)。
QOJ7837 挑战积和式
首先我们考虑 \(k=2\) 大概是一个凸包的做法。考虑做 dp,但是直接设 \(f_{i,j}\) 代表选了 \(i\) 个数,乘积为 \(j\) 的最大代价。考虑最后的 \(\prod b_i\) 一定小于 \(V=\max a_i\),所以 \(k\) 最大有效值只有 \(O(\log V)\)。
Lemma. 1:对于一个集合 \(S\) 满足所有 \(x \in S\) 都有 \(x \le \frac{2}{3}\) 并且 \(\sum_{x \in S} x=1\),存在一个子集 \(T \subset S\) 使得 \(\frac{1}{2} \le \sum_{x \in T} \le \frac{2}{3}\)。
那么考虑我们把 \(\prod b_i\) 分成两半,每一半的值域是 \(O(V^{2/3})\)。那么设 \(f_{i,j}\) 算出来 dp 值后枚举 \(a+b=k\),然后每次枚举做一次卷积,总时间复杂度 \(O( V^{2/3} \log^2 V)\)。
Lemma. 2:对于一个集合 \(S\) 满足所有 \(x\in S\) 都有 \(x \le \frac{1}{3}\) 并且 \(\sum_{x \in S} x = 1\),存在一个子集 \(T \subset S\) 使得 \(\frac{1}{2} \le \sum_{x \in T} \le \frac{2}{3}\),并且 \(T\) 的大小刚好为 \(S\) 的一半。
证明:考虑直接把 \(S\) 升序排序后,然后选择偶数位置的数组成 \(T\) 即可。
那么我们说明到了,只用 \(a=1,b=k-1\) 和 \(a = \lfloor \frac{k}{2} \rfloor,b=\lceil \frac{k}{2} \rceil\) 合并,合并出来的答案就是合法的。这几个值可以倍增快速求,时间复杂度 \(O(V^{2/3} \log V \log \log V)\)。
QOJ7872 崩坏天际线
这个 8s 真不是给 \(O(nq)\) 过的吗。首先考虑 sub3,我们观察到,每时每刻本质不同的区间只有 \(O(q)\) 个,具体来说:
- 没有经过任何分割的区间只有 \(q\) 个。
- 经过了若干分割,但是保留了原来的某个端点,这样的区间至多只有 \(2q\) 个。
- 经过了若干分割,没有保留原来的端点,这样的区间至多只有 \(q\) 个。
考虑如何对这些区间进行维护,首先第一种区间我们直接随便维护,势能下来是对的。对于第二种区间,我们不妨以左端点为某个分割点 \(p\),右端点不同为例。我们考虑下一次进行分割并且分割点在 \(x\),并且 \(p\) 后面的第一个分割点是 \(x\),那么我们需要把 \(p\) 右端点 \(>x\) 的切成两个部分。这是一个线段树分裂的形式,直接做就是 \(O(q \log q)\) 的。
最后考虑加上时间维度,我们考虑做 cdq 分治,每次考虑先对左右区间分别进行分治,把信息返回到当前层并给左区间加入右半区间的贡献,时间复杂度 \(O(q \log^2 q)\)。
QOJ7980 区间切割
首先考虑 AB 性质,每个区间只会被切割 \(O(\log m)\) 次,考虑给每个区间势能修改,最开始的想法是给线段树每个节点开个 set 把标记挂在上面。但是可以离线,记 \(t_i\) 代表位置 \(i\) 的删除时间,那么区间 \([L_i,R_i]\) 第一次被切割的时间是 \(\min t_{L{i}+1 \sim R_{i}-1}\)。时间复杂度 \(O((n+m) \log n)\)。
现在考虑只有 A 性质,我们扫描线,对于一个操作 \((x,l,r)\) 在 \(l\) 处把 \(t_x\) 置为对应时间,在 \(r+1\) 处把 \(t_x\) 置为 \(\infty\)。拿线段树维护这个东西,时间复杂度 \(O(n \log^2 m + m \log m)\)。
现在考虑只有 B 性质,一个区间会经历 \(O(n)\) 次有效的切割。我们考虑设计一个势能,让一个区间切到一定部分再处理。具体来说,我们把一个区间 \([l,r]\) 等分成三份 \([l,ml],[ml,mr],[mr,r]\)。那么如果切到了 \([l,ml],[mr,r]\) 之间,这次切割是无效的。
继续延续 A 性质的离线做法,设 \(t_i\) 代表位置 \(i\) 的删除时间,那么 \(\min t_{ml \sim mr}\) 就是 \(i\) 的更新时间,记这个位置为 \(p\),考虑找出来更新前的左右端点来继承。这等于说找 \(p\) 左右第一个比 \(t_p\) 小的位置。用 ST 表预处理可以做到 \(O((n +m) \log n)\)。
最后考虑没有 B 性质,一样离线做就可以,线段树二分可以做到 \(O(n \log^2 m + m \log m)\)。
26. 9. 5 和 26. 9. 7
AT_agc036_d [AGC036D] Negative Cycle
考虑把原图转化到差分约束上面去,那么不存在负环等价于存在一组可行解 \(x_{1 \sim n}\),我们不妨对 \(x\) 做差分得到 \(s_i = x_i - x_{i+1}\)。那么首先有 \(s_i \ge 0\),那么边分为两种:
- \(i<j\):那么此时的限制是 \(x_i - 1 \ge x_j\)。换个形式写就是 \(s_i + s_{i+1} + \cdot\cdot\cdot + s_{j-1} \ge 1\)。
- \(i>j\):那么此时的限制是 \(x_i + 1 \ge x_j\)。换个形式写就是 \(s_j + s_{j+1} + \cdot\cdot\cdot + s_{i-1} \le 1\)。
所以如果区间和 \(=0\),则第一类边需要删除,如果区间和 \(\ge 2\),第二类边需要删除。经过观察,我们发现 \(0 \le s_i \le 1\),因为 \(s_i\) 如果 \(\ge 2\) 则一定会删掉 \((i,i+1)\) 而不优。那么就可以做 dp 了,设 \(f_{i,j}\) 代表考虑了 \([1,i]\),上一个为 \(1\) 的位置是 \(j\),二维前缀和可以把转移优化到 \(O(n^3)\)。
CF1361E James and the Chase
有向强连通图的 DFS 树没有横叉边。我们以任意一个点为根,搜出来任意一棵生成树。那么对于根节点,它是有趣的就当且仅当树上不存在前向边。
假设我们已经找到了一个合法的根节点 \(p\),现在考虑对于树上的每个点 \(u\) 判断合法性。
- 首先 \(u\) 需要可达所有点,所以 \(u\) 的子树必须要存在一条返祖边,并且恰好连到 \(u\) 的祖先节点。
- 其次 \(u\) 到所有点只能有一条路径,那么只能恰好有一条到祖先上的返祖边,并且这条返祖边连接的点 \(v\) 也是合法的。
时间复杂度 \(O(k(n+m))\),这里 \(k\) 是随机次数。
CF2061G Kevin and Teams
这个题也太难了。首先我们可以构造说明上界是 \(\left \lfloor \dfrac{(n+1)}{3} \right \rfloor\),考虑如何构造。
我们维护一条同色链,每次给一端试图加入一条边。如果加入的边同色就直接加入,否则弹出两条边,分析可知构造到上界。
P7816 「Stoi2029」以父之名
感觉是和 P15869 差不多的手法,我们把一个点的所有连边两两进行配对。具体来说,优先给同颜色进行配对。配对完后剩下一条 \(1\) 边,讨论:
- 如果剩下了一条 \(2\) 边,把这两条边配对。
- 否则建立一个虚点,连一条 \(1\) 边到这个点并进行配对。
时间复杂度 \(O(n+m)\)。
P13358 [GDCPC 2024] 小班课
题解几把在说啥。首先进行按优先级顺序增广的二分图匹配(匈牙利算法),我们猜测答案就是最大匹配,首先记 \(i\) 的匹配点为 \(p_i\)。我们下面证明,一定存在一个匹配顺序,使得 \(i\) 恰好匹配到 \(p_i\):
- 在这种情况下,我们在某个时刻能够选择 \(i\) 当且仅当 \(i\) 在 \(p_i\) 之前优先级的目标点被全部占满。
- 如果点 \(i\) 存在某个比 \(p_i\) 优先级更高的目标点的点被 \(j\) 匹配了,那么我们给 \(j \to i\) 连一条边,能构造出方案当且仅当这张图没有环,是一张 DAG。
- 考虑反证,如果这张图有环,记环上的点是 \(x_1 \sim x_k\),对应匹配的点是 \(y_1 \sim y_k\),那么在原二分图上一定形如 \(y_1 \to x_1 \to y_2 \to x_2 \to ... \to y_k \to x_k \to y_1\),其中 \(y_i \to x_i\) 是匹配边,那么我们在加入 \(x_k\) 时,首先会遍历到 \(y_1\),而此时 \(y_1 \to y_k\) 构成一条增广路,那么 \(x_k\) 会直接和 \(y_1\) 匹配,所以不会出现环。
那么每次找一个合法的学生就做完了,时间复杂度 \(O(n^3)\)。
P13592 [NWRRC 2023] Loops
我们发现对于一个 \(2 \times 2\) 的小网格,如果我们确定了左上和左下,左上和右上的偏序关系,还一定存在一种合法的定向方式。所以从左上往右下去做就可以做到时间复杂度 \(O(nm)\)。
更进一步,我们发现可以钦定每一行单增,第一列单增,方案是唯一的。
AT_agc034_d [AGC034D] Manhattan Max Matching
草首先可以直接用四个点,不需要 cdq 优化建图,因为 \(|x_1 - x_2| = \max(x_1-x_2,x_2-x_1)\),不合法的一定不优。记起点终点为 \(S,T\),四个点为 \(A,B,C,D\),考虑模拟费用流。
给这六个点两两之间开个堆维护增广的过程即可,时间复杂度 \(O(kn \log n)\),这里 \(k\) 是一个大概 \(20\) 的常数。
P13342 [EGOI 2025] Wind Turbines / 风力涡轮机
首先建出来最小生成树,问题等价于最多删除最小生成树上的 \(r_i - \ell_i\) 条边,使得 \([\ell_i, r_i]\) 互不连通,求最小代价。
不妨先考虑 \(\ell_i +1 = r_i\) 的情况,建出来 Kruskal 重构树,那么 \(\ell_i,r_i\) 在重构树上的 LCA 就是我们要删除的边。扩展到更一般的情况,我们发现我们会删掉这些点两两之间的 LCA。
考虑点对 \((i,j)\) 的 LCA 在序列上其实可以支配对,具体来说,我们对原树做启发式合并,每次把小子树合并到大子树上面的时候,我们考虑找到每个小子树的点在大子树里面对应的前驱和后继(下标上),这样的总对数是 \(O(n \log n)\) 的。
直接看起来这是一个二维的数颜色,但这其实是假的二维数颜色。扫描线 \(r\),把所有修改和询问挂在 \(r\) 上,我们对于每个颜色,维护 \(pre_i\) 代表 \(\le r\) 的区间中,左端点最大的是多少。每次加入 \(l\) 比较 \(l\) 和 \(pre_c\) 的大小,然后问题是区间加,单点查询,树状数组即可。
时间复杂度 \(O((m+q) \log n + n \log^2 n)\)。
P10851 [EGOI 2024] Make Them Meet / 活动面基
我有一个看起来特别吊的做法,懒得写了。
P12493 [集训队互测 2024] 子集和
首先对两个前缀和做差分,问题变为从一个前缀 \([1,l]\) 选一个,一个后缀 \([r,n]\) 选一个,并且这个前缀和后缀不交。考虑做猫树合并。我们不妨从 \(l \le M \le r\) 的情况下手。我们需要知道左半部分 \([1,M] \setminus \{i\}\) 的信息,直接枚举 \(i\) 显然不可接受,但是背包的方案数显然可以直接相加。
也就是说,对于左半部分,我们需要对每个 \(i\) 查询 \([1,M] \setminus \{i\}\) 的信息,然后对这个信息做一遍前缀和。这个东西是不是可以大力线段树分治,那么做完了,时间复杂度 \(O(nm \log^2 n + qm)\)。这个题不是傻逼吗。
QOJ7854 这不是一道数据结构题
我们先考虑树怎么做。考虑在某个点 \(u\) 合并所有子树,设第一棵子树内的点为 \(p_{1 \sim k}\),那么其他子树一个必要的合法条件是必须插空 \(p_i\) 来放。我们以 \(1\) 号节点为根,那么和一号节点相邻的每个点,子树都应该构成一段完整的区间,否则显然不合法。
我们又发现这个区间的长度就等于子树大小,那么对于 \(1\) 节点来说,我们枚举 \(\text{deg}_1 !\) 种顺序,然后向下递归,可以得到唯一的一种方案。换句话说总方案数是 \(n \prod \text{deg}_i !\)。
这个时候有个神秘的建模,我们把问题看作是在一个圆上,那么区间不交或包含就是弦不相交。现在我们来考虑基环树,我们仍然找到 \(1\) 号点的所在位置 \(u\),那么分类讨论:
- 如果 \(u\) 不在环上:限制条件和树一样,\(u\) 节点贡献 \(\text{deg}_i!\) 的贡献。
- 如果 \(u\) 在环上:那么这个大环必须要顺时针或逆时针递增,这个大环会贡献 \(2\) 的贡献。
更进一步,我们对原图缩点,建出来圆方树,记点双个数为 \(c\),那么方案数就是 \(n2^c \prod \text{deg}_i!\),这里 \(\text{deg}_i!\) 只对原点进行计算。
最后我们考虑怎么判断是否存在合法方案,充分条件是对于每个超过两个点的点双,都要由一个大环和若干不相交的弦构成,考虑缩二度点,首先需要缩到两个节点。我们发现这无法保证存在一个大环使得每个点都在上面,但是缩二度点的过程显然可以把所有环上的边给找出来,我们只需要判断这些边即可,时间复杂度 \(O(m \log m)\)。
26. 9. 8
P16997 【MX-S15-T3】「DLESS-5」旅游定价
草怎么是傻鸟题,化简一下总收费的式子,写一下就是 \(n\sum p_i + n\sum q_i\)。
考虑如果给定 \(x_{1} \sim x_n\),我们该如何计算答案。那么写出来是 \(p_i + q_j \le |x_i-a_j|\),移项,也就是 \(p_i \le |x_i-a_j| - q_j\),我们把右边看作是一个绝对值函数在 \(x_i\) 处的点值。哦那我们不需要考虑给定 \(x_1 \sim x_n\),因为 \(x_i\) 可以直接取 \(\min(|x_i-a_j| - q_j)\) 最大的一项。
总贡献是 \(\sum\max (\min(|x_i-a_j| - q_j)) + \sum q_j\),我们看作是每个绝对值函数可以向下面移动若干步,贡献则会用移动步数加上关键点高度计算。首先如果一个函数在另一个函数的上方,肯定向下移动不劣。记函数为 \(f_j(x)\),记 \(g(x)\) 是下轮廓。
稍作转化,我们考虑直接对 \(g(x)\) 做 dp,一个 \(g(x)\) 是最优的当且仅当对于每个 \(S_i\),都至少有一个 \((x_k,p_i)\) 落在上面,还要要求每个 \((a_i,-q_i)\) 都落在上面。由于关键点折线的长度很短,我们考虑设 \(f_{i,S}\) 代表考虑到了 \(x=i\),前面长度为 \(15\) 的折线的 dp 值为 \(S\)。我们把一个 \(S_i\) 集合的贡献挂到 \(\max(S_i)\) 去算。
考虑到 \(x=a_i\) 时所有转移式都要带上 \(-g(x)\) 的贡献,考虑把这个贡献拆到每一步决策上,具体来说每一步决策的贡献都是这一步的决策 \(c_i \in \{-1,1\}\) 乘上后面 \(x=a_i\) 的个数减去后面 \(\max(S_i)\) 的个数。考虑刷表转移:
- 这一个点不是某个 \(\max(S_i)\):
- 如果在此从向上走变为向下走:\(f_{i,S'} - sum\to f_{i+1,S}\),这里要求 \(S'\) 的末尾是 \(0\),\(S\) 的末尾是 \(1\)。
- 继续走:\(f_{i,S} +sum (-1)^{S_0} \to f_{i+1,S}\),这里要求 \(S\) 和 \(S'\) 的末尾相同。
- 这一个点是某个 \(x=a_i\):
- 如果在此转折:\(f_{i,S'} + sum \to f_{i+1,S}\):这里要求 \(S'\) 的末尾是 \(1\),\(S\) 的末尾是 \(0\)。
- 这一个点是某个 \(\max(S_i)\):
- 这个时候 \(O(k)\) 计算一下前 \(k\) 项的贡献即可。
由于这个 dp 值域非常大,需要改一改在 \(a_i\) 之间 dp。那么做完了,时间复杂度 \(O(nk2^k)\)。
CF1844G Tree Weights
这几把是给人做的吗?首先我们有:
我们考虑,如果我们把这个式子对 \(2\) 取模,会有什么影响。我们发现,最后那一项必然等于 \(0\),由于我们已知 \(\text{dep}_1=0\),那么我们可以推出来 \(\text{dep}_1 \sim \text{dep}_n\) 的奇偶性。
那么我们继续考虑,如果对 \(4\) 取模呢?那么我们发现,最后那一项变成了常数,也就是我们可以推出来 \(\text{dep}_1 \sim \text{dep}_n\) 对 \(4\) 取模的值。依次类推,我们可以知道 \(\text{dep}_1 \sim \text{dep}_n\) 的值。那么做完了,时间复杂度 \(O(n \log V)\)。
QOJ837 Giant Penguin
首先大力点分治,考虑每个顶点最多位于 \(k\) 个简单环这个条件,也就是说当前分治中心 \(u\) 下面最多有 \(k\) 条横叉边,我们把这 \(2k\) 个点拉出来。首先我们跑一遍以这 \(2k\) 个点为起点的 BFS,在当前分治中心按时间顺序遍历所有查询。
我们考虑一次查询的答案分成两个部分,一种是走到分治中心 \(u\) 再走下去,另一种是直接走到 \(2k\) 个点之一然后走过去,这些东西都可以大力维护,时间复杂度 \(O(nk \log n)\)。
一个多重背包技巧
多重背包算方案的时候,假设某个物品有 \(a\) 个容量为 \(b\),可以直接塞一个权值为 \((a+1)b\),方案权值为 \(-1\) 的 \(0/1\) 物品,然后看作是大小为 \(b\) 的完全背包。证明很显然。
感觉这个不是特别难,但是好像没往这个方向想过?
CF1458F Range Diameter Sum
树上圆理论,记 \(f(u,r)\) 代表点 \(u\) 的 \(r\)-邻域,那么显然有两个观察:
Lemma. 1:\(f(u,r_1)\) 包含 \(f(u,r_2)\) 当且仅当 \(r_1 \ge r_2 + \text{dist}_{u,v}\)。
Lemma. 2:记 \(c(S)\) 代表包含 \(S\) 集合的最小邻域,不妨设 \(r_1 \ge r_2\),那么有 \(c(f(u,r_1) \cup f(v,r_2)) = f(\text{mov}(u,v,(-r_1+r_2+\text{dist}_{u,v}) /2),(r_1+r_2+\text{dist}_{u,v}) /2)\)。
考虑分治,假设我们当前处理区间 \([l,r]\),中点为 \(M\),我们记 \(h_i\) 代表前缀,后缀形成的圆,我们用 \(h_l\) 把所有 \(r\) 分为三类:被包含于 \(h_l\),和 \(h_l\) 无包含关系,包含 \(h_l\),这三类都可以做指针。
现在我们来考虑怎么做贡献,首先第一类和第三类的贡献计算是平凡的,考虑第二类,答案是左边的半径加上右边的半径,最后加上两点间距离,这个两点间距离通过点分树可以快速实现,时间复杂度 \(O(n \log^2 n)\)。
CF1168D Anagram Paths
首先我们考虑合法条件,不难发现合法条件是对于任意的叶子节点 \(i,j\),设 \(s_{i,0\sim 25}\) 代表 \(i\) 到根的 \(26\) 个字母的出现次数,设 \(t_i\) 代表 \(i\) 到根的问号个数,需要满足有 \(\sum |s_{i,c} - s_{j,c}| \le t_i + t_j - 2t_{\text{LCA}}\)。
这样判断太复杂了,我们考虑找一个更简单的判断方式,具体来说,在每个点 \(u\),我们对于每个 \(c\) 维护每个叶子到 \(u\) 路径上的 \(s_{i,c}\) 的可能最大值,我们需要这些最大值的总和加起来小于等于深度差。记 \(u\) 到叶子的距离为 \(\Delta d\),那么条件写出来也就是 \(\sum_c \text{maxs}_{i,c} \le \Delta d\)。那么答案也就是 \(\min(\Delta d_u - \sum \text{maxs}_{i,c} + s_{u,x} + t_{u,x})\)。
这里 \(t_{u,x}\) 指的是 \(u\) 到根问号加 \(x\) 的数量。这个时候直接大力 ddp 应该是 \(O((n + q) \log n |\Sigma|) \sim O((n + q) \log^2 |\Sigma|)\) 的,但是我们考虑,每次修改只会影响某个点向上的一条链,我们二分出来容易做到 \(O((n + q) \log^2 n |\Sigma|)\)。
哦,妈的,我们发现我们判掉合法性后,在根节点算这个几把答案就是对的,全二可以做到时间复杂度 \(O((n+q) (\log n + |\Sigma|))\)。
P10789 [NOI2024] 登山
简单萌萌题。
诶我操看错题了,怎么从每个起点都要走,把我们的 dp 改为倒过来的,重新梳理一下思路:
- 首先我们定义 \(f_u\) 代表从 \(u\) 节点走到 \(1\) 节点的方案数,我们按深度从小到大转移 dp。
- 记当前转移的点为 \(u\),那么我们考虑 \(u\) 的转移是从某个子树内的点 \(x\) 再跳到某个祖先上面去,然后把这个祖先的 dp 值继承给 \(u\)。
- 我们考虑,一个 \(x\) 何时可以进行这样的转移。首先祖先点的深度 \(d_0\) 必须要小于等于 \(x \to u\) 的路径的最小限制深度。其次这个祖先点需要满足 \(d_0 < d_u\)。
- 先考虑 \(h_i=0\),我们考虑对于一个点 \(x\) 的区间 \([l_x,r_x]\),我们在深度等于 \(l_x\) 的深度时把这个 \(x\) 加入某个数据结构,在 \(r_x+1\) 删除它。我们查询 \(u\) 的时候需要查询 \(u\) 的子树所有转移点的值之和。由于加入 \(u\) 需要更新这些 \(x\) 的权值,但是我们发现更新的 \(x\) 一定位于 \(u\) 的子树,所以我们只需要做线段树上的带权加即可。
- 现在我们考虑 \(h_i \ne 0\),现在的问题是,某些点可能吃不到 \(u\) 的贡献。也就是我们需要限制 \(u \to x \to y\) 这条转移路径中,\(u \to x\) 的限制最小值的深度需要大于等于 \(d_y\)。我们对这个部分的贡献进行刷表转移,因为刷表更方便限制。假设当前刷表转移的点是 \(u\),那么首先我们把 \(u\) 子树所有限制深度 \(<d_u\) 的点染黑。那么转移形如从 \(u\) 走到某个点,然后一直跳父亲,并且不能经过黑色点。
- 换句话说,我们需要给当前集合 \(S\) 每个点到根一段极长的白色点加上 \(f_u\),这个东西可以线段树带权加,区间加权值,区间带权加,单点修改实现,这个东西可以用树状数组写历史和,容易做到 \(O(n \log n)\)。
题解区的一个思路是,我们给 \(l_i,r_i\) 做差分,那么我们差分出来的结果是 \(s_{\min(r_j,v_{i \to j})} - s_{l_j-1}\)(这里 \(l_i,r_i\) 是反着的),右边那个东西就是 \(l_i = r_i\) 的情况,我们枚举 \(\min(r_j,v_{i \to j})\),分 \(r_j\) 和 \(v_{i \to j}\) 枚举,枚举 \(r_j\) 后向上是一条链,枚举 \(v_{i \to j}\) 后向上选一个 \(i\) 向下选一个 \(j\) 容易做到 \(O(n \log n)\)。
26. 9. 9
今天怎么只做了两个题。。。
P14451 [ICPC 2025 Xi'an R] Epilogue of Happiness
P16452 [APIO 2026] APIOBike
我们考虑拿每个点的 \(a_i-b_i\) 作为一个点的权值。首先把权值为 \(0\) 的叶子节点给删掉,一个显然的上界是 \(2n-2\),我们考虑从随便一个点出发,按子树的权值和排序后从大往小走构造肯定是合法的。
一个显然的下界是 \(2n - 2 - \text{diam}\),这个下界显然取不到,但是启发我们比上界小的贡献一定是一条链提供的。如果我们确定了这条链,那么我们最优的走路方案一定形如:
- 对点 \(u\),我们遍历子树权值和 \(\ge 0\) 的儿子,如果这个儿子不是链上的节点,就走它。然后遍历所有遍历所有子树权值和 \(<0\) 的儿子,同样限制要不是链上的节点。
- 进入链上的儿子递归构造。
我们考虑更简洁地描述这个策略, 我们记路径上的点为 \(p_1 \sim p_k\),记 \(S(u,v)\) 代表以 \(u\) 为根 \(v\) 子树的权值和。那么所有点分为 \(S(p_{i+1},p_i) \ge 0\) 和 \(S(p_{i+1},p_i)<0\) 两类。首先第二类点走一遍必然不合法,但是我们考虑对于路径上每个极长的二类点段 \([l,r)\),由于 \(r\) 是合法的,那么也就是说可以先从 \(l \to r\) 并遍历所有正子树,然后遍历 \(r\) 的所有非 \(p_{r+1}\) 子树,然后从 \(r \to l\) 回来填所有负的子树,然后最后从 \(l\) 重新回到 \(r\),也就是需要 \(3(r-l)\) 的次数来填完。
也就是说,一条路径 \(p_1 \sim p_k\) 能提供的最大贡献是 \(\sum[S(p_{i+1},p_i) \ge 0] - \sum[S(p_{i+1},p_i)<0]\),考虑对这个做换根 dp,设 \(f_u\) 代表 \(u\) 子树,从 \(u\) 出发的答案,那么转移是 \(f_u = \max (f_v + \text{sgn}(S(v, u)), 0)\),换根 dp 容易做到 \(O(n)\) 时间复杂度。
CF1442E Black, White and Grey Tree
这个题我是不是做过啊。首先我们考虑,只有黑点和白点怎么做?首先一个极大同色连通块肯定是一起删除,缩完了肯定是黑白点相间。那么我们每次考虑删掉所有最外圈的同色点,那么答案应该是直径加一除二向上取整。
现在考虑我们加入了这个灰色节点,直接大力做 dp 即可,时间复杂度 \(O(n)\)。
CF1712F Triameter
我们考虑设 \(f_u\) 代表 \(u\) 和离 \(u\) 最近的叶子节点的距离,那么两个点 \(u,v\) 的最短路是 \(\min(f_u+f_v+X,\text{dist}(u,v))\)。首先我们考虑二分答案,两个条件分别是 \(f_u+f_v+X \ge \text{mid}\) 和 \(\text{dist}(u,v)\ge \text{mid}\),我们枚举 \(v\),把所有点按 \(f_i\) 从小到大排序,那么 \(u\) 的取值是一段后缀。
我们维护每个后缀的直径,然后 \(O(n\log n) - O(1)\) 预处理 LCA 来维护后缀的直径,可以做到时间复杂度 \(O(nm \log n)\)。
观察到答案的上界是 \(n\),我们考虑枚举答案。枚举 \(u\) 然后每次尝试增加 \(\text{mid}\) 即可,时间复杂度 \(O(nm + n \log n)\)。
树论讲课,但是写的 typora 丢了 /dk
P15732 [JAG 2024 Summer Camp #2] Do Make Segment Tree
这个题不是闵可夫板子吗,我们考虑斜率最大也只有 \(O(N)\),直接维护分段函数暴力合并就是 \(O(QN^2)\) 的。
QOJ5438 Half Mixed
首先我们考虑 \(n \times m\) 的子矩阵个数,这个是 \(2S_0 = \dfrac{nm(n+1)(m+1)}{4}\),我们考虑纯的子矩阵个数为 \(S_0\)。我们考虑怎么判断是否有解,一个必要的条件是 \(S_0\) 是整数,也就是 \(n\) 模四等于 \(0\) 或 \(3\) 或者 \(m\) 也如此,我们不妨设是 \(n\):
我们考虑把一行都染成同一种颜色,那么问题压缩到 \(m=1\),也就是说我们需要找到一组 \(L_i\),使得 \(\sum L_i = n \wedge \sum L_i^2 = \dfrac{n(n-1)}{2}\)。我们考虑这个东西每次贪心取最大的就是对的。我也不知道为啥,但是就是对的,大概感觉一下就是这个 \(\sum L_i^2\) 项增加的很快,会留出来一些项填小数。时间复杂度 \(O(nm)\)。
QOJ8079 Range Periodicity Query
根据 border 那一套理论,周期应该呈现 \(O(\log n)\) 个等差数列。我们直接找出 \(S_k\) 的这 \(O(\log n)\) 段等差数列然后去区间里面判断即可,但是我好像不会啊?
我们考虑如果固定了 \(d\),那么合法的 \(k\) 应该是一段前缀,也就是说每个点初始都有一个 \(k_{\max}\),查询等价于查询区间 \(k_i \le k\) 的所有 \(i\) 中,\(p_i\) 的最小值,这是一个二维偏序,离线下来扫一遍即可。
QOJ8074 Multiply Then Plus
首先 3log 肯定是容易的,线段树分治之后随便维护一些东西即可。我们考虑如何做静态的区间查询,我们考虑建立线段树,给线段树上每个节点维护一个凸包,把所有询问排序后在凸包上面做指针就是 \(O((n+q) \log n)\) 的。
现在考虑加入了单点修改,线段树分治,考虑到查询在某个固定的时间,我们可以把查询挂在到根链上的每一个节点上,这样就有 \(O(n \log n)\) 次修改,\(O(q \log n)\) 次查询,套用上面的做法时间复杂度 \(O((n+q) \log^2 n)\)。
P3780 [SDOI2017] 苹果树
首先 \(a_i \ge k\) 的部分没有用,然后选择的苹果个数肯定 \(\le n+k\)。一个暴力 dp 的想法是枚举最大深度,然后设 \(f_{u,i,0/1}\) 代表 \(u\) 的子树选了 \(i\) 个苹果的最大权值,是否触碰到最大深度,这样做是 \(O(n^3)\) 的,太劣了。我们复杂度的来源有两个部分,一个部分是树形背包的卷积,另外一个部分来自枚举的最大深度。
首先我们考虑把枚举的那个最大深度给干掉,这 \(k\) 个点我们看作是,选择一条树上的主链,然后选择 \(k\) 个附加的点。我们改一下 dp 状态,设 \(f_{u,k}\) 代表考虑 \(u\) 的子树,\(u\) 是主链,并且 \(u\) 用了 \(k\) 个附加点的最大代价,设 \(g_{u,k}\) 代表考虑 \(u\) 的子树,\(u\) 不是主链,并且 \(u\) 用了 \(k\) 个附加点的最大代价。我们考虑如果我们把一个非主链给算成主链,答案显然不优。这个转移是 \(O(nk^2)\) 的。
考虑到树上依赖背包可以拍到 DFS 序上面做,把这个最大深度弱化为选择某个点并且提供到根的点数的容量。然后在 DFS 序上面做前缀 dp 即可,时间复杂度 \(O(nk)\)。
26. 9. 18
AT_agc056_b [AGC056B] Range Argmax
考虑对原序列建立笛卡尔树,然后对于一个区间 \([l,r]\),我们会选择 \(k\) 个断点 \(x_{1 \sim k}\),然后把区间断成 \([l,x_1),(x_1,x_2),\cdot\cdot\cdot (x_k,r]\) 这 \(k+1\) 个区间,并且计算区间 \([L_i,R_i] \subseteq [l,r]\) 并且和某个断点交上的贡献,这些区间可以任选它们区间中的一个断点。
我草,怎么是排列啊,那么断点只会有一个 \(x\),我们会把区间断成 \([l,x)\) 和 \((x,r]\),并且计算所有 \([L_i,R_i] \subseteq [l, r]\) 并且 \(L_i \le x \le R_i\) 的贡献。我们考虑这样直接 dp 的问题在于,我们会把一组 \(x_{1 \sim m}\) 给多次算入贡献,考虑建立一个单射来做去重。
那么我们来考虑怎么通过一组 \(x_i\) 倒着生成 \(p_i\),很明显我们很想让一个区间的最大值尽可能靠前来钦定单射,换句话说我们从大到小填 \(p_i\),然后每次需要找到最前面的满足要求的位置 \(q\) 把最大值填进去,回到刚刚 dp 的视角来看,这等于说我们找到 \([1,q)\) 的最大值 \(q_0\),然后存在一个区间包含 \([q_0,q]\) 来限制。
那么可以 dp 了,设 \(f_{l,r,q}\) 代表考虑区间 \([l,r]\),最大值的取值范围 \(\ge q\) 的方案数,时间复杂度 \(O(n^3)\)。
AT_agc067_b [AGC067B] Modifications
我们考虑倒着来看所有操作,那么是给区间没有覆盖的位置全部打上覆盖标记。我们考虑这么做的好处,我们发现,那个排列 \(p_i\) 可以直接丢掉,因为对同一个区间染色第二次直接无效。
考虑如何检验一组 \(a_i\) 是否合法,每次找到一个区间颜色全部相同的 \([L_i,R_i]\) 并且把区间所有数全部变成通配符,合法当且仅当最终全部是通配符。容斥对不合法的序列计数。
我们考虑不合法的序列长啥样,肯定会有一些位置没有被替换成通配符,并且没有一个区间会内部全部是同色点。设 \(f_{l,r}\) 代表用区间 \([l,r]\) 的所有子区间操作的答案,开一个辅助数组 \(g_{l,r,p}\) 代表 \(r\) 是断点,上一个颜色不同的断点在 \(p\) 的方案数。设 \(ok_{l,r,p}\) 代表用 \([l,r]\) 所有子区间操作能否把 \(p\) 染色。枚举 \(r\) 前面第一个断点的位置 \(i\),分 \(i\) 的颜色和 \(r\) 相同或者不同分开讨论:
转移的限制是 \(ok_{p+1,r-1,i}=0\),然后计算 \(f\),先加上 \(C^{r-l+1}\) 然后枚举右边第一个断点容斥,时间复杂度 \(O(n^4)\)。
CF1864H Asterism Stream
我们只需要对所有 \(x<n\) 的操作序列带权 \(2^{\text{len}}\) 然后求和即可。枚举 \(\times 2\) 进行的操作次数 \(k\),每个 \(+1\) 对最终的 \(x\) 贡献为 \(2^0 \sim 2^k\),把操作序列用 \(c_0 \sim c_k\) 描述,需要计数有多少 \(2^k+\sum c_i2^i <n\),贡献为 \(2^{-k-\sum c_i}\)。
添加一个 \(c'\),计数 \(c' + \sum c_i2^i = n - 2^k - 1\) 的 \(c\) 序列。我们考虑左式求和的每个二进制位 \(2^k\),分析每个 \(c_i\) 是否能对 \(2^k\) 造成贡献,这等价于说对于 \(i \in [0, k]\),让 \(c_i\) 的二进制位 \(2^{k-i}\) 为 \(1\),或者 \(c'\) 的 \(2^k\) 位为 \(1\)。我们按 \(k\) 从小到大扫描,每次确定 \(c',c_i\) 中对应的二进制位,并且记录上一位的进位,时间复杂度 \(O(T \log^4 n)\)。
26. 9. 21
CF1830D Mex Tree
首先考虑暴力 dp,我们对一个子树 \(u\) 来看,记它的颜色为 \(c_u\),则 \(u\) 到子树内所有点的 \(\text{mex}\) 要么是 \(\text{mex}(c_u)\) 要么是 \(2\)。那么设 \(f_{u,i,0/1}\) 代表考虑了子树 \(u\),与根节点连通的极大同颜色块的大小 \(i\),根节点颜色为 \(0/1\)。直接做树形背包转移是 \(O(n^2)\) 的。
直接二分图染色应该会取到一个下界,取较小侧染成颜色 \(1\),两边的点的个数分别为 \(A,B\),那么答案就是 \(n^2 - \min(A,B)\)。这个下界实际上很大,并且损耗的部分 \(\le n\),所以上面那个 dp 第二维 \(i\) 开到 \(O(\sqrt n)\) 即可,但是这样空间开不下。经过我们的分析,某个子树子树外独立的 \(\ge B\) 的子树最多只有 \(\frac{n}{B}\) 个,所以写精细一点空间就是 \(O(n)\) 的。
P16319 [ICPC 2023 Jinan R] 铁路环游
首先一个平凡的想法是,我们设 \(f_{i,L,k}\) 代表考虑了 \([1,i]\),当前连续段左端点在 \(L\),已经放了 \(k\) 条铁路。把 \(L\) 这一维去掉考虑做断点转移,设 \(f_{i,k}\) 代考虑到了 \([1,i]\),已经放了 \(k\) 条铁路的最大的分。那么转移有:\(f_{i,k} \to f_{i+1,k}, f_{i,k} + w(i+1,i+j) \to f_{i+j,k+j}\)
这里的 \(w(i,j)\) 是被 \([i,j]\) 完全包含的区间权值和。那么考虑把 \(f_{i,j}\) 的状态改一改,改成 \(f_{i,i-j}\),那么转移一形如 \(f_{i,i-k} \to f_{i+1,i-k-1}\),转移二形如 \(f_{i,i-k} + w(i+1,i+j) \to f_{i+j,i-k}\)。线段树可以做到 \(O(n^2 \log n)\) 的复杂度。
我们考虑这个东西是怎么转移的,我们会把区间挂在右端点上面,然后每次做的操作是前缀加,查询全局 \(\max\)。但是我们发现 \(f_{i,j}\) 是关于 \(j\) 单调递增的,也就是说这个前缀加每次会把一段前缀给做类推平。
具体来说我们给 \([1,p]\) 做完前缀加后,不停检查 \(p\) 的后一个元素,如果这个元素被 \(p\) 干掉了,那么就删掉这个元素。那么每个时刻最右边还存在的元素就是最大值。并查集维护双向链表即可,时间复杂度 \(O(n(n+m)\alpha(n))\)。
CF1750G Doping
首先我们枚举 \(p\) 和 \(p'\) 的 LCP 长度 \(L\) 和 \(p_{L+1}\),记这前 \(L\) 个位置的上升段有 \(c_2\) 个。上升段有 \(k\) 个等价于说有 \(n-k-1\) 对相邻的位置满足上升,我们考虑钦定一些位置满足 \(a_{i+1}=a_i+1\)。首先我们记 \(a_{i+1}=a_{i}+1\) 并且 \(a_i,a_{i+1}\) 都没有在 LCP 填过的数量为 \(c_0\),然后 \(a_{L}+1\) 是否被填我们记作 \(c_1\),那么有方案数:
这样得到了一个 \(O(n^4)\) 的做法,首先我们考虑对于一个 \(L\) 来说,枚举的 \(p_{L+1}\) 产生的贡献不一样当且仅当 \(c_0,c_1\) 不一样,但是有效的 \((c_0,c_1)\) 的对数是 \(O(1)\) 的,这样复杂度就降到了 \(O(n^3)\)。
考虑用 GF 看这个卷积,设 \(F_i(z)=(1+z)^i\),\(G_i(z) = \sum s_iz^x\)。那么答案应该是若干个 \(F_i(z) \times G_i(z)\) 的和,这个东西可以用秦九韶算法做到 \(O(n^2)\)。
QOJ5308 RPG Pro League
考虑对这个东西建图,左部点是 \(A,B,C,AB\) 四个点,右部点是 \(2^3-1\) 个子集对应的点,左边代表需求,右边代表人,二分答案 \(t\),那么边分为三种:
- 源点 \(S\) 到左部点,流量为 \(t\)。
- 左部点 \(L\) 到右部点 \(R\),流量为 \(\infty\),要求 \(L \cap R \ne \varnothing\)。
- 右部点到汇点 \(T\),流量为人的数量。
那么我们实际上只需要检查 \(S \to T\) 的最大流是否等于 \(4t\) 即可。实际上这个不需要二分,答案就是 \(\min \left ( \frac{|N(S)|}{|S|} \right )\),现在考虑怎么求最小代价,考虑对这个东西做费用流,我们发现 \(S \to L\) 和 \(R \to T\) 的边都不会退流,这东西直接跑一个费用流复杂度是对的。
现在考虑带修改,把某个 \(R \to T\) 的费用给改掉了,我们需要判断这个费用流是否出现了一个负环,这等于求 \(T \to R\) 的最短路,求出来之后更新信息即可,时间复杂度 \(O(n \log n)\)。
QOJ8047 DFS Order 4
我们考虑如何判定一个 DFS 序是否是可以被生成的,首先 \(p_1=1,p_2=2\),那么这个时候我们讨论 \(3\) 节点的位置,要么是 \(2\) 的儿子要么是 \(2\) 的兄弟,假如 \(p_3=3\) 我们不妨钦定它位于儿子,否则位于兄弟。
换句话说,我们给 DFS 序和树建立一个双射,我们对满足以下条件的树 \(T\) 计数:
- 每个点的权值都大于其父亲的权值。
- 每个点的权值都小于其父亲前一个儿子子树内的最大点。
考虑到如果树形态固定了,先不考虑第二个限制,我们给节点之间连边代表偏序关系,那么 \(T\) 生成的 DFS 个数为 \(\frac{n!}{\prod siz_i}\)。把 \(n!\) 提取出来然后对下面做 dp。对第二个限制做容斥,做完容斥形式很好看。
设 \(f_{i,j}\) 代表大小为 \(i\) 的树,并上一个大小为 \(j\) 的子树方案数,那么考虑转移,枚举第一个儿子:
-
如果 \(u\) 只有一个儿子:\(f_{i-1,0} \times \frac{1}{i+j-1} \to f_{i,j}\)。
-
否则我们枚举这个儿子的大小 \(k\),那么有转移 \(\frac{1}{i+j-1} \sum_{k=2}^{i-2} f_{i-k,j} \times (f_{k,0} - f_{k,i-1-k+j}) \to f_{i,j}\)。
时间复杂度 \(O(n^3)\)。
26. 9. 22
CF704B Ant Man
懒得写了,总之大概意思就是这个东西不用再加两维 \(0/1/2\) 来单独处理 \(s,t\) 的情况。
QOJ9865 Dolls
我们考虑一个区间可以缩成一个数,那么所有子区间都可以缩成一个数,那么直接大力贪,需要做一个划分状物。首先直接二分炸了,倍增找到在哪个范围里面二分复杂度是 \(O(n \log^2 n)\)。
AT_arc230_a [ARC230A] Meeting on Tree
我们考虑对每条边有贡献 \(\min(A,B)\),这里 \(A,B\) 是两边的黑点数量,也就是说我们需要求:
我们把 \(\min\) 给拆掉并且加上 \(x \le y\) 的限制:
那么 \(x \le y\) 的条件也就是 \((x-1+n-i-y) \le n-i-1\),然后范德蒙德卷积,时间复杂度 \(O(n)\)。
26. 9. 23
P11405 [RMI 2020] 秘鲁 / Peru
我们先考虑一个暴力 dp,设 \(f_{i}\) 代表拍死 \([1,i]\) 的最小代价。考虑转移,有:
首先单调栈加树状数组可以直接给这个 dp 优化到 \(O(n \log n)\),然后其次这个 dp 显然可以单调队列优化,优化后的问题是对队头和队尾加入删除,需要维护最小值,这个双栈模拟队列并且重构就可以做到 \(O(n)\)。
P14721 [RMI 2025] 橙子 / Oranges
首先初始的 \(k\) 个点一定要形成一组点覆盖,我们考虑怎么判定一组方案是否合法,首先管理员应该会尽可能把所有海豚往叶子上赶,具体来说,我们每次找到所有儿子都是叶子的节点 \(u\),那么合法当且仅当 \(u\) 和 \(u\) 的所有儿子至多只有一个位置没有海豚。
QOJ964 Excluded Min
首先我们考虑怎么求 \(F(1,n)\),我们考虑维护 \(\text{cnt}[0,k]-k\) 的最大值,然后可以做到 \(O(n)\)。我们考虑枚举答案,然后每次把答案合法的区间给踹掉。枚举答案后要做的相当于说给包含某个点 \(p\) 的区间 \(-1\),然后查询 \(\max\)。
我们不难发现如果一个区间 \([l_1,r_1]\) 包含区间 \([l_2,r_2]\),那么 \([l_1,r_1]\) 的答案一定 \(\ge [l_2,r_2]\) 的答案,那么也就是说我们只需要保留一系列极大的左右端点升序的区间,那么就可以线段树维护了,时间复杂度 \(O(n\log n)\)。
CF1672I PermutationForces
我们维护出来一个序列 \(A_i=p_i-i\),一次操作可以看作是选择某个位置 \(x\),然后给满足 \((i < x\wedge p_i >p_x)\) 的位置的 \(A_i\) 加一,给满足 \((i>x \wedge p_i < p_x)\) 的位置的 \(A_i\) 减一。
我们考虑这样一个策略,每次选择 \(|A_i|\) 最小的一个位置进行操作,不妨设这个点的 \((i,p_i)\) 在 \(y=x\) 上方,那么这个点的左上方必定都是给 \(|A_i|\) 减一,右下方且在 \(y=x\) 右下方必然也是给 \(|A_i|\) 减一,而 \((i,p_i)\) 到 \(y=x\) 这段区域肯定没有点,所以肯定是不劣的。
我们对 \(p_i \ge i\) 的所有点进行考虑,我们发现,对于两个点 \((i,j)\),如果满足 \(i < j \wedge p_i > p_j\),那么 \(i\) 一定在 \(j\) 后面被删掉,所以可以仿照 QOJ964 只保留一系列上升点列,这样修改就从二维降到了一维,然后可以线段树在 \(O(n \log n)\) 时间复杂度解决。
这一个降维的策略大概意思是对某些二维(或区间)上的删除的问题,如果点之间存在某种偏序关系可以降掉一维。具体需要证某个点在另外一个点后被删除。
P14463 【MX-S10-T4】『FeOI-4』呼吸之野
首先经典地,我们把 \(\ge x\) 的数看作 \(1\),否则看作 \(-1\),一个区间中位数 \(\ge x\) 就等价于区间和 \(\ge 0\)。
对于每个左端点 \(i\),我们找到一个 \(f_i\) 代表 \([ f_i,i]\) 是满足区间和 \(\ge 0\) 且区间长度 \(\ge k\) 的最大的 \(l_i\),那么我们只需要对这 \(O(n)\) 个区间判断合法性,所以得到了一个 \(O(n^2)\) 的暴力。如果某个时刻 \(t\),有 \(f_i \le f_j \le j \le i\),那么 \([f_j,j]\) 之后一直会被 \([f_i,i]\) 支配,也就是说我们需要对每个位置求出一个存在时间 \([1,t_i]\)。
我们首先考虑对某个固定的 \(x\) 怎么算答案,考虑对序列扫描线,当前扫到了 \(i\),记前面第一个保留下来的位置是 \(j\),\(i\) 如果要保留下来需要满足 \(f_j < f_i\),我们对 \([j+1,i]\) 的区间和进行讨论:
- \(a[j+1,i] >0\):那么这个时候显然有 \(f_j < f_i\),\(i\) 一定会保留下来。
- \(a[j+1,i] \le 0\):这个时候如果不考虑区间长度的限制 \(f_j\) 一定对于 \(i\) 合法,也就是说因为长度的限制导致 \(f_i\) 无法取到 \(f_j\),也就是 \(j-x+1 \le f_i \le i-x+1\)。
那么我们对于第二种情况维护 \(s_{0 \sim i-k}\) 的历史前缀 \(\min\),每次更新 \(i\) 都把历史和清空,然后丢到线段树上面二分可以在 \(O(n \log n)\) 时间求出 \(t_i\),查询直接二分可以做到 \(O(n \log n + q\log^2 n)\)。
我们考虑再反着求一个 \(g_i\) 代表 \([i,g_i]\),然后这个 \(f\) 和 \(g\) 一一对应,可以直接做到 \(O(n \log n + q\log n)\)。
26. 9. 26
CF547E Mike and Friends
首先给查询差分,然后我们把查询看作是,建出 \(S_1 \sim S_r\) 的 ACAM,然后把 \(S_k\) 对应节点 \(+1\),然后对于每个 \(S_i\) 对应的点,遍历其到根节点上的所有节点 \(u\),然后查询 \(u\) 的 fail 树上到根链的标记点个数,最后把这些全部加起来。
我们扫描线 \(r\),每次加入一个串,并且给这个串根链路径上的点 \(u\),在其 fail 树上给根链 \(+1\),然后查询 \(k\) 时查询单点权值即可,时间复杂度 \(O((n+q) \log n)\)。
26. 9. 27
CF2053G Naive String Splits
首先我们考虑一个贪心策略,不妨设 \(|x|<|y|\) 能放 \(y\) 就放 \(y\),否则放 \(x\),这个贪心策略在 \(x\) 不是 \(y\) 的非整周期时成立。否则我们考虑判断接下来的串是否是 \(y+x\),如果是填 \(y\) 否则填 \(x\) 即可,均摊下来时间复杂度 \(O(m \log m)\)。注意这里需要特判 \(x,y\) 最小整周期相同的情况。
CF710F String Set Queries
注意到如果这个问题是静态的实际上非常简单,我们需要考虑的问题是如何强制在线。我们考虑维护一个线段树结构,每次给末尾加叶子即可,时间复杂度 \(O(n |\Sigma| \log n)\)。
CF2211G Rational Bubble Sort
我们考虑把 \((i,S_i)\) 看作是一个点,那么原题就变成了一张折线图,操作等于说是把 \(i-1\) 到 \(i+1\) 给拉平。首先如果一个点在 \((0,0) \to (n,S_n)\) 下方则显然有合法构造,否则如果有连续两个点不在线上无解,否则可以把不在线上的点全部拉回线上。
P12763 [POI 2018 R2] 诗集 Book of poetry
我们先尝试来分析一下答案下界,首先我们把 \(a_i\) 全部加一然后对 \(s\) 取模,答案就是排列前缀和数组对 \(s\) 取模等于 \(0\) 的数量。首先如果所有 \(a_i\) 相同则我们可以直接暴力,我们观察到,否则大部分情况答案都是 \(0\)。
归纳构造,不妨设当前的集合为 \(S\),先删掉所有的 \(0\) 单独处理,那么每次我们考虑构造,提取出 \(S\) 中出现次数最多的数 \(x\):
- 如果 \(x\) 填到末尾合法:那么直接填入 \(x\) 即可。
- 否则我们找到出现次数第二多的数 \(y\),把 \(y\) 填入末尾,下一个必然是把 \(x\) 填入末尾。
分析我们的操作,每次必然给最大次数减一,最坏情况也会给次大次数减一,如果数列没有绝对众数则答案必然为 \(0\),现在考虑如果有绝对众数,这么填也是不劣的,时间复杂度 \(O(n \log n)\)。
P12923 [POI 2021/2022 R3] 模板 2 / Szablon 2
首先我们发现 \(S\) 一定是文本串的一个前缀,或者说 \(\text{rev}(S)\) 一定是文本串的一个前缀。我们首先考虑第一种情况,我们首先枚举这个前缀 \([1,p]\),那么暴力的做法我们用 Z 函数先求出来某个后缀和这个前缀的 LCP 长度,然后拿个指针跳一下即可。
我们发现这样做,然后每次选择左端点最大的一个进行扩展,跳两次必然加 \(p\),那么总的遍历次数是调和级数 \(O(n \log n)\)。直接上线段树的复杂度是 \(O(n \log^2 n)\) 的。哦这个可以扫描线并查集做到 \(O(n \log n \alpha(n))\)。
P5592 美德的讲坛
好像假了,待补。
P9935 [NFLSPC #6] 啊,忘记了。
首先删去所有的空串,然后尽可能合并前缀和后缀的非通配串,把全部是通配符的串加入答案,那么剩下的串形如:\(A,*A,A*,*A*,A*A\) 五种形状。那么我们考虑首先判掉 \(A\) 的形状,我们首先枚举 \(A\) 的每个前后缀来处理掉 \(*A,A*\) 的情况,然后给所有 \(*A*\) 串的 \(A\) 建 ACAM,把 \(A\) 在上面走的每个点到根进行覆盖并求出来覆盖权值。最后剩下的问题是 \(A*A\) 的形状,给这些串再建出来一个 ACAM,然后在 fail 树上面做二维数点即可,这一大部分的时间复杂度是 \(O(n (|\Sigma| + \log n))\)。
现在我们可以把 \(A\) 踹掉了,现在剩下的形状还有 \(*A,A*,*A*,A*A\) 四个形状,那么我们考虑 \(*A*\) 一定可以加入贡献,还剩下 \(*A,A*,A*A\),首先对 \(A*A\) 类串建立 ACAM,然后 \(A*A\) 串对其的贡献是二维数点形式,而 \(*A,A*\) 的贡献形式是一维数点形式,这一部分的时间复杂度也是 \(O(n(|\Sigma| + \log n))\) 的。
现在我们可以把 \(A*A\) 也踹掉了,那么剩下的还有 \(*A\) 和 \(A*\),这两个部分是独立了,继续再做一个 fail 树上的一维数点即可,那么做完了,总时间复杂度 \(O(n(|\Sigma| + \log n))\)。这他妈不是模拟吗。
26. 9. 28
P13352 [GDCPC 2024] 腊肠披萨
考虑用 ACAM 去刻画 border 信息,先把所有串的 ACAM 建出来,然后遍历每个串,给 \(S_{i,j}\) 的所在位置打一个颜色权值二元组标记 \((i,C^j)\),那么现在的问题是对于所有串的末尾点,求出来其在 fail 树上每次颜色第一次碰到的时候的权值之和。
那么考虑对于每个串 \(S_i\),我们找到其每个末尾 \(j\) 对应的点 \(p_{i,j}\),然后把这些点全部拉出来建虚树后算贡献,时间复杂度 \(O(|S| (\log |S| + \Sigma|)\)。进一步我们发现这个虚树很蠢,我们直接对某个 \(S_i\) 跑 KMP 就能求出来,然后权值和在树上打差分标记,时间复杂度 \(O(|\sum S|\times |\Sigma|)\)。
P9926 [NFLSPC #6] 所以 k 小生成树怎么做?
首先我们回顾次小生成树的求法,我们先建出来最小生成树,然后选择一条非树边把某条树边给顶掉,然后要求变化的权值尽可能小。考虑反悔贪心,考虑我们加入一条非树边 \((u,v,w)\) 后会有什么影响。
我们考虑给每一个状态找到若干状态后继,然后拿堆来一个一个取出前 \(k\) 小,我们考虑对于一张树 \(T\),真正的状态后继总共有 \(O(m)\) 个。直接存进去复杂度爆了,我们考虑我们先找到树的最小后继 \(T_0\),如果后续操作取出了 \(T_0\) 再加入次小后继 \(T_1\),如果取出了 \(T_1\) 再加入次次小后继 \(T_2\),以此类推。
现在的问题是,我们需要对某棵树求前 \(m\) 小的替换边,换句话说需要多次查询路径最大值,如果直接倍增时间复杂度是 \(O(mk \log n)\) 的,考虑反过来,我们对每条树边求它的最小覆盖边,按权值从小到大加入非树边,然后做路径覆盖,这样就可以并查集维护了,时间复杂度 \(O(k \log k + m \log m + mk + nk\alpha(n))\)。
QOJ7402 Chiaki Chain Counting
首先不难发现 \(k=m-n+1\),我们首先考虑一个 \(O(Tn)\) 的做法,我们枚举主链长度 \(L\),选择 \(L\) 个标号并且排列,然后从这 \(L\) 个选择 \(k\) 个定点,再给这 \(k\) 个点排列。
我们首先考虑某个点下面挂了大小为 \(x\),环大小为 \(y\) 的子树的权值,这个方案数和 \(y\) 无关,我们现在要考虑的事情是把 \(n-L\) 划分成 \(k\) 段,每一个长度为 \(x\) 段的权值为 \(x!\),并且长度有大于等于的限制,需要求出权值积的和。
这么做有点难搞,我们考虑看作是先把环固定下来了,然后往里面插入若干元素,转化一下,现在有 \(k\) 个内部有顺序区分的盒子,有 \(S=n-L-\frac{k(k+5)}{2}\) 个不同的小球放入。这等价于先给小球排列,然后再做插板,那么总的方案数就是:
但是这个还不对,因为端点的位置会算重复,那么我们的贡献分为三种,左右端点都是叶子,左端点是叶子,右端点是叶子,左右端点都不是叶子。首先解决左右端点都是叶子的方案数,这个只需要改一改组合数的上指标即可。如果左右端点都不是叶子,我们需要钦定左右端点下面直接连着环。如果左端点或者右端点是叶子,那么需要给一端的下面挂一个环,总方案数是:
但是很不幸这个几把东西在 \(k \le 3\) 不对,我们把 \(k=1,2,3\) 手动算掉,这一部分比较恶心,这里略去。现在考虑 \(k>3\) 的情况。
很傻逼这个式子还是错的,因为为我们会把一棵树算多次,我们在草稿纸上手玩一下,我们发现,如果主链的某个断点下挂了一个环 \(A\),并且和其在主链上最近的是环 \(B\),并且 \(B\) 和主链之间有至少一个点,那么我们 \((A,B)\) 算贡献会多一个 \(2\) 的系数。如果两端都这样就会算出来一个 \(4\) 的系数。
我们考虑算出来系数为 \(1,2,4\) 三种情况的答案,我们记 \(\text{sum1}, \text{sum2}, \text{sum200}, \text{sum201}, \text{sum211}, \text{sum3}, \text{sum30}, \text{sum31}\) 分别代表两边不挂叶子,两边挂叶子并无限制,两边挂叶子并主链上第一个和最后一个都是紧贴着主链的环,两边挂叶子并主链上有一边都是紧贴着主链的环,两边挂叶子并主链上第一个和最后一个都是不紧贴着主链的环,单边挂叶子并不限制,单边挂叶子并第一个是紧贴着主链的环,单边挂叶子并第一个不是紧贴主链的环。那么有:
然后其中 \(\text{sum201},\text{sum31}\) 的方案除以 \(2\),\(\text{sum211}\) 的方案除以 \(4\),然后相加,这样我们得到了一个 \(O(Tn)\) 的做法,还无法通过。
然后接下来我们把这所有和式全部通过范德蒙德卷积缩到一起,记 \(N'=n-\frac{k(k+5)}{2}-2\),最终答案是:
时间复杂度 \(O(T)\),可喜可贺。
yukicoder 1001 注文の多い順列
题意:给定 \(t_{1 \sim n}, x_{1 \sim n}\),如果 \(t_i=0\) 则 \(p_i \le x_i\),否则 \(p_i \ge x_i\),求排列 \(p\) 的数量,\(1 \le n \le 5000\)。
我们把条件写成 \(\prod_{i,t_i=0}[p_i \le x_i] \times \prod_{i,t_i=1}(1-[p_i \le (x_i-1)])\),然后把所有 \((t_i,x_i)\) 排序(如果 \(t_i=1\) 就给 \(x_i\) 减去 \(1\)),那么考虑设 \(f_{i,j}\) 代表考虑到了 \(i\),前面有 \(j\) 个数钦定了上界,那么转移系数为 \(i-j\),时间复杂度 \(O(n^2)\)。
gym106559 Buhăiești
题意:给定长度为 \(n\) 的,值域在 \([1,m]\) 的序列 \(B_i\),求有多少个序列 \(A_i\),满足 \(A\) 的字典序严格小于 \(B\),并且对于每个前缀 \(i\) 都满足 \(\text{mex}(A[1:i]) \le \text{mex}(B[1:i])\)。
首先我们枚举 \(A,B\) 的 LCP,记为 \(L\),开始求出来 \(B_i\) 的前缀 \(\text{mex}\) 值 \(s_i\)。考虑 \(\text{mex}(S) \le X\) 其实也就是说 \(S\) 中至少有一个 \([0,X]\) 值域的数没有出现。考虑设 \(f_{i,j,k}\) 代表考虑了前 \(i\) 个数,然后当前 \(j\) 没有出现,\([0,j)\) 都出现了,并且前面有 \(k\) 个 \(> j\) 的数。现在考虑转移:
- 当前 \(A_i < j\):转移 \(f_{i,j,k} \to f_{i+1,j,k} \times j\)。
- 当前 $A_i = j $:设一个辅助数组 \(g_{i,j}\) 代表考虑了值域 \([1,i]\),还有 \(j\) 个剩余数的答案,初始把 \(f_{i,j,k} \to g_{j+1,k}\),那么每次转移枚举这一层给多少个关键点,乘上一个组合数 \(\binom{j}{x}\) 然后转移到下一层。
- 当前 \(A_i > j\):转移 \(f_{i,j,k} \to f_{i+1,j,k+1}\)。
现在加上枚举的 LCP,我们需要对第一位的大小进行限制,再开一维 \(0/1\) 代表是否填了 LCP 的下一个位置,那么做完了,时间复杂度 \(O(n^4m)\)。
QOJ10210 Misunderstood … Missing
考虑把贡献提前给算掉,设 \(f_{i,j,k}\) 代表考虑到了 \(i\),钦定后面有 \(j\) 个位置攻击,这些攻击位置的下标和为 \(k\),直接转移即可,时间复杂度 \(O(n^4)\)。

浙公网安备 33010602011771号