2026.9 做题记录 2
2026.9.16
P15732 [JAG 2024 Summer Camp #2] Do Make Segment Tree
定义状态函数 \(f_{u,x}\) 为考虑完 \(u\) 子树,且 \(B_u = x\) 的最小操作次数和。
记 \(l_u\) 为 \(u\) 左儿子,\(r_u\) 为 \(u\) 右儿子。那么:\(f_{u,x}=(\min\limits_{a+b=x}^{}f_{l_u,a}+f_{r_u,b})+|x-A_u|\)。
注意到 \(f_{u}\) 是一个下凸的函数,做 \((\min,+)\) 卷积后仍然是下凸的。那么考虑用闵可夫斯基和优化这个。
维护差分数组 \(d_{u,x} = f_{u,x}-f_{u-1,x}\)。那么 \(d_u\) 可以通过以下方式得到:
- 将 \(d_{l_u},d_{r_u}\) 归并得到 \(d_{u}\)。
- 将 \(d_{u,-\infin}\) 增加 \(|-\infin - A_u|\),并将 \(x\in (-\infin,A_u]\) 的 \(d_{u,x}\) 减少 \(1\)。
- 将 \(x\in [A_u+1,+\infin)\) 的 \(d_{u,x}\) 增加 \(1\)。
显然 \(d_{u,x}\) 的种类数 \(T(u)\) 满足 \(T(u)\le \max(T(l_u),T(r_u))+O(1)\)。所以 \(d_{u,x}\) 的连续段只有 \(O(n)\) 个。
那么对每个 \(u\) 维护这 \(O(n)\) 个连续段 \((len,\Delta)\) 就行了。最后答案即为前缀和最小值。
时间复杂度 \(O(n2^n+qn^2)\)。
P15502 [ICPC 2025 APC] Book Sorting
首先每本书最多移动到最左边一次,最右边也是。
如果 \(p_i\) 要移动到最左边,且存在 \(p_j < p_i\) 不移动到最左边。此时一定需要花费 \(1\) 的代价交换它们。那么不如把 \(j\) 也移动到最左边。则移动到最左边的元素构成的集合可以由区间 \([1,L]\) 表示。
同理,移动到最右边的元素构成的集合可以由区间 \([R,n]\) 表示。
那么答案等价于:\(\min\limits_{1\le L\le R \le n}^{}f(L,R)+(L-1) + (n-R)\)。其中 \(f(L,R)\) 为下标区间 \([L,R]\) 中逆序对数量,即 \(f(L,R)=\sum\limits_{i=L}^{R}\sum\limits_{j=L}^{i-1}[pos_j>pos_i]\)。
记 \(g(L,R) = f(L,R)+(L-1)+(n-R)\)。有:
满足四边形不等式。那么直接跑分治就行了。时间复杂度 \(O(n\log^2 n)\)。
P12550 [UOI 2025] Reversal ABC
注意到对于一个 \(\text{A}\),如果它跟后面的 \(\text{B}\) 换了,就不可能再跟前面的字符换。因为能跟前面的字符换当且仅当这个字符是 \(\text{C}\)。但此时我们是将 \(\text{AB}\) 变成了 \(\text{BA}\),能出现 \(\text{CA}\) 当且仅当 \(\text{B}\) 前面一个 \(\text{C}\) 换到它后面去了。但 \(\text{CB}\) 不能换。同理如果它跟前面的 \(\text{C}\) 换了,就不可能再跟后面的字符换。
对于 \(\text{B},\text{C}\) 也是一样的。
那么可以描述成:
- 将序列拆成若干个区间 \([l_i,r_i]\)。每个区间只有至多两种字符。定义 \(f(l,r)\) 为对区间 \([l,r]\) 内部最多能换的次数,则序列操作次数等于 \(\sum f(l_i,r_i)\)。求这个的最大值。
先考虑 \(f(l,r)\) 怎么求。不妨设 \([l,r]\) 中只有 \(\text{A},\text{B}\)。
发现最后序列形如 \(\text{BB}\dots \text{BBAA}\dots \text{AA}\)。则 \(f(l,r)\) 等于区间 \([l,r]\) 中每个 \(\text{B}\) 前面 \(\text{A}\) 的数量和。即 \(f(l,r)=\sum\limits_{i=l}^{r}\sum\limits_{j=i+1}^{r}[s_i=\text{A}\land s_j = \text{B}]\)。
令 \(\text{B}\) 匹配 \(\text{A}\),\(\text{C}\) 匹配 \(\text{B}\),\(\text{A}\) 匹配 \(\text{C}\)。记 \(v_i\) 为 \([1,i]\) 中是 \(s_i\) 的匹配的字符数量,\(sum_{i,x}\) 为 \([1,i]\) 中 \(s_j= x\) 的 \(v_j\) 之和,\(cnt_{i,x}\) 为 \([1,i]\) 中 \(s_j=x\) 的数量。则 \(f(l,r) = sum_{r,\text{B}}-sum_{l-1,\text{B}}-(cnt_{r,\text{B}}-cnt_{l-1,\text{B}})\times cnt_{l-1,\text{A}}\)。
定义状态函数 \(dp_{i}\) 为最后一个划分区间右端点为 \(i\) 的最大价值和。记 \(pos_{1,i}\) 为 \(i\) 前面第一个与 \(s_i\) 不同的下标,\(pos_{2,i}\) 为 \(i\) 前面第一个与 \(s_i,s_{pos_{1,i}}\) 都不同的下标。
那么转移有:
- \(j\in [pos_{1,i},i-1]\)。\(dp_i\gets dp_{j}+0\)。
- \(j\in [pos_{2,i},pos_{1,i}-1]\)。记 \(x,y\) 满足 \(\{x,y\}=\{s_{pos_{1,i}},s_i\}\) 且 \(x\) 匹配 \(y\)。\(dp_i\gets sum_{i,x}+(dp_{j}-sum_{j,x}+cnt_{j,x}\times cnt_{j,y})-cnt_{i,x}\times cnt_{j,y}\)。
- \(j\in [0,pos_{2,i}-1]\)。不能转移。
斜率优化即可。时间复杂度 \(O(n)\)。
2026.9.17
QOJ8074 Multiply Then Plus
对修改线段树分治。那么每个完整的时间区间都有若干个插入 \((k,a_i,b_i)\) 的操作,且总数是 \(O((n+q)\log n)\) 的。
对于询问,因为是单个时间点的询问,所以可以挂到线段树这个时间点到根所有完整的时间区间上。那么每个完整的时间区间都有若干个询问 \((x,l,r)\) 的操作,且总数是 \(O(q\log n)\) 的。
单独拿出一个完整的询问区间来看。记有 \(m_1\) 个插入操作,\(m_2\) 个查询操作。先将 \(k,l,r\) 放一起离散化。复杂度 \(O((m_1+m_2)\log (m_1+m_2))\)。建立区间线段树,将询问放到 \(O(\log (m_1+m_2))\) 个完整区间上。那么插入操作先挂到叶子上,每次相当于是合并两个上凸壳。整体复杂度是 \(O(m_1)\) 的。合并到当前点后把挂在这个点上的询问都处理掉。提前将询问按照 \(x\) 从小到大排序,这样挂在每个完整区间上的询问都是关于 \(x\) 单增的。那么就可以用指针扫一遍求答案了。均摊 \(O((m_2+m_1)\log m_1)\)。
那么整体时间复杂度就是 \(O((n+q)\log^2 n)\) 的。
QOJ5438 半混合
一个 \(n \times m\) 的矩形有 \(\frac{n(n+1)m(m+1)}{4}\) 个子矩形。
则纯子矩形和混合子矩形都有 \(\frac{n(n+1)m(m+1)}{8}\) 个。
问题变成找到一种构造,使得恰好有 \(\frac{n(n+1)m(m+1)}{8}\) 个纯子矩形。
因为 \(8 \mid n(n+1)m(m+1)\),所以 \(n,m\) 中一定有一个数满足 \(x\bmod 4 =0\) 或 \(x\bmod 4=3\)。
也就是说,存在 \(n\) 或 \(m\) 满足 \(\frac{x(x+1)}{4}\) 是整数。不妨设 \(m\) 满足条件。
那么分成 \(n\) 列,每列都是一个 \(1\times m\) 的矩形。相当于求一组满足:
- \(\sum x_i = m\)。
- \(\sum \frac{x_i(x_i+1)}{2}=\frac{m(m+1)}{4}\)。
的解。每次贪心删最大的 \(x\) 就是对的,不知道为啥。
时间复杂度 \(O(nm)\)。
QOJ8079 Range Periodicity Query
判定 \(s[1:k]\) 是否是 \(s\) 的周期。等价于判定 \(s[1:|s|-k]\) 和 \(s[k+1,|s|]\) 是否相等。
对每个长度 \(k\) 找到区间 \([l_k,r_k]\)。使得 \(k\) 是 \(S_{l_k\sim r_k}\) 的周期。显然有 \(l_k = k\)。二分哈希做到 \(O(n\log n)\)。
再到着枚举长度扫一遍就可以求答案了。线段树做到 \(O(n\log n)\)。
P3780 [SDOI2017] 苹果树
首先注意到这个 \(t-h \le k\) 就相当于随便在选了苹果的点中钦定一个点的深度作为 \(h\)。因为当 \(h\) 不是最大深度时不优。
限制了祖先必须选,考虑按照 dfn 序做 DP。
对于一个点 \(u\),对它进行完决策后有两种情况:
- \(u\) 子树继续选点。下一步决策 dfn 序中 \(u\) 下一个点,这个点的父亲一定是 \(u\)。保证了祖先必须选。
- \(u\) 子树不再选点。记 \(r_u\) 为 \(u\) 子树中 dfn 序的最大值,下一步决策 dfn 序为 \(r_u+1\) 的点。显然,这个点一定是 \(u\) 的某个祖先的另一个儿子,保证了祖先必须选。
定义 \(dfn_u\) 为 \(u\) 的 dfn 序,\(id_x\) 为 dfn 序为 \(x\) 的点 \(u\) 编号,\(r_u\) 为 \(u\) 子树中 dfn 序最大值。
定义状态函数 \(f_{i,x}\) 为考虑完 dfn 序的前 \(i\) 个点,苹果总数 \(t\) 等于 \(x\) 且没有钦定某个点时的最大价值和;\(g_{i,x}\) 为考虑完 dfn 序的前 \(i\) 个点,苹果总数 \(t\) 减去钦定的点深度 \(h\) 等于 \(x\) 时的最大价值和。
考虑转移,现在已知不计算 \(i\) 时的 \(f'_{i},g'_i\),有:
然后对 \(j\in \{i+1,r_i+1\}\) 更新:
单调队列优化做到 \(O(n^2 + nk)\)。因为 \(f_{*,x}\) 满足 \(0\le x \le n+k\),\(g_{*,x}\) 满足 \(0\le x \le k\)。
注意到对于一个 \(f_{i,x}\),如果最后钦定的深度小于 \(dep_{id_i}\),不如直接在 \(i\) 这里钦定了。所以 \(x - dep_{id_i} > k\) 的状态一定无用。所以 \(f_{i,x}\) 实际上有用的 \(x\) 满足 \(dep_{id_i}\le x \le k+dep_{id_i}\)。总量就是 \(O(nk)\) 的。
整体时间复杂度为 \(O(nk)\)。
2026.9.18
AT_agc056_b [AGC056B] Range Argmax
考虑从大到小填数,这样一个区间第一次填的数就是最大值,那么下标也就确定了。
记 \(pos\) 为当前最大值的位置,对于一个区间 \([L,R]\):
- \(R < pos\)。不确定 \(x\)。
- \(L\le pos \le R\)。确定 \(x\) 为 \(pos\)。
- \(pos<L\)。不确定 \(x\)。
这样就变成两个子问题了。但实际上我们只在意下标,所以直接这么做会算重。
\(pos\) 将剩下不确定 \(x\) 的区间分成 \(R<pos\) 和 \(L>pos\) 两类,记 \(pos'\) 为 \(R < pos\) 这一类区间中第一个确定的 \(x\)。
当 \(pos' < L_0\) 时先确定 \(pos'\) 再确定 \(pos\) 是等价的。因为 \(pos' < L \le R < pos\) 的区间是不受 \(p_{pos}\) 和 \(p_{pos'}\) 大小限制的(因为一定比它们的最小值小);\(R < pos'\) 的区间与 \(pos\) 无关;\(L > pos\) 的区间与 \(pos'\) 无关;\(L \le pos \le R\) 的区间因为 \(pos' <L_0\) 所以与 \(pos'\) 无关;\(L \le pos' \le R < pos\) 的区间与 \(pos\) 无关。
那么我们可以加强枚举的限制来做到不重不漏。即枚举 \(pos\) 后 \(R < pos\) 这一类需要满足第一次枚举的 \(pos'\) 在区间 \([L_0,pos)\) 中。
定义状态函数 \(f_{l,r,p}\) 为只确定被 \([l,r]\) 包含的区间的 \(x\),且 \(p\) 为第一次枚举的 \(pos\) 的方案数。
记 \(L_{l,r,pos}\) 为包含 \(pos\) 且被 \([l,r]\) 包含的区间 \([L,R]\) 中,\(L\) 的最小值。
枚举 \(pos\),当存在被 \([l,r]\) 包含且包含 \(pos\) 的区间 \([L,R]\) 时转移为:
- \(f_{l,r,pos}\gets f_{l,pos -1,y}\times f_{pos+1,r,x}[L_{l,r,pos}\le y]\)。
当 \([l,r]\) 中不存在区间 \([L,R]\) 时,初始化 \(f_{l,r,n}=1\)。答案为 \(\sum\limits_{x} f_{1,n,x}\)。
后缀和优化做到 \(O(n^3)\)。
AT_agc067_b [AGC067B] Modifications
按照时间倒着做。那么一个点第一次被填的值就是它最终的值。
考虑判定一个序列 \(a\) 是否合法。相当于每次选择一个值相同的区间 \([L_i,R_i]\),然后把 \([L_i,R_i]\) 中所有元素变成通配符。要求最后所有元素都是通配符。
这个操作本身是没有性质的。但是如果确定了最后哪些元素没有变成通配符,就一定可以知道哪些区间是合法的。这样就产生了子结构。
那么考虑容斥。定义状态函数 \(f_{l,r}\) 为能将 \([l,r]\) 中所有元素变成通配符时,\(a\) 序列的数量。总方案数为 \(C^{r-l+1}\)。记 \(p_{1,2,\dots,k}\) 为某个不合法的序列 \(a\) 中,最后没有变成通配符的下标。可知 \([l,p_1-1],[p_1+1,p_2-1],\dots,[p_{k-1}+1,p_k-1],[p_k+1,r]\) 这些 \(a\) 的子区间都是合法的。且不存在 \([L,R]\),满足:所有 \(p_i\in [L,R]\) 的 \(a_{p_i}\) 相同。
定义状态函数 \(g_{l,r,p}\) 为考虑完所有 \(p_i \le r\),最后一个在 \(r\),且极长的 \(a_{p_i}\) 相同的后缀起始点(第一个不同值位置 \(+1\))为 \(p\) 的方案数。对于转移:
- \(p_1=r\)。\(g_{l,r,l}\gets f_{l,r-1}\times C\)。要求不存在 \([L,R]\),使得 \(L \le r = R\)。
- \(p_i = r,i>1\)。
- \(a_{p_i}=a_{p_{i-1}}\)。\(g_{l,r,p}\gets g_{l,r',p}\times f_{r'+1,r-1}\)。要求不存在 \([L,R]\),使得 \(p \le L \le r'\le R\le r\)。
- \(a_{p_i}\ne a_{p_{i-1}}\)。\(g_{l,r,r'+1}\gets g_{l,r',p}\times f_{r'+1,r-1}\times (C-1)\)。要求不存在 \([L,R]\),使得 \(p \le L \le r'\le R\le r-1\)。
对于 \(f_{l,r}\),初始 \(f_{l,r} = C^{r-l+1}\)。枚举 \(p_k = x\),有 \(f_{l,r}\gets -\sum \limits_{p}g_{l,x,p}\times f_{x+1,r}\),要求不存在 \([L,R]\),使得 \(p\le L \le x \le R \le r\)。
初始化 \(f_{i,i-1}=1\)。答案为 \(f_{1,n}\)。时间复杂度 \(O(n^4)\)。
CF1864H Asterism Stream
记 \(p(i)\) 为走到 \(i\) 的概率,答案即为 \(\sum\limits_{i=1}^{n-1}p(i)\)。
对于每个 \(+1\) 操作的实际贡献,记 \(cnt\) 为其后面 \(\times 2\) 操作数量,那么就是 \(2^{cnt}\)。
那么整个操作的贡献可以用 \(s_{0\sim k}\) 表示。其中 \(s_i\) 为后面 \(\times 2\) 操作数量为 \(i\) 的 \(+1\) 操作数量,其中 \(k\) 为 \(\times 2\) 的操作数量。则贡献可以表示为:\(2^{k}+\sum\limits_{i=0}^{k}2^{i}s_i\)。对答案的贡献为 \(\frac{1}{2^{k+\sum\limits_{i=0}^{k}s_i}}\)。
问题变成对 \(2^{k}+\sum\limits_{i=0}^{k}2^{i}s_i<n\) 的 \(s\) 计数。
枚举 \(k\),再添加一个数 \(s'\),使得问题变成对 \(s'+\sum\limits_{i=0}^{k}2^is_i = n - 2^k-1\) 的 \((s',s)\) 计数。将 \(s'\) 和 \(s_i\) 用二进制表示,变成:
因为 \(s'_{x},s_{i,j}\in \{0,1\}\),所以对于任意 \(x\),\(0\le s'_{x}+\sum\limits_{i=0}^{\min(k,x)}s_{i,x-i} \le k+2\)。求和时这个量级的进位是可以接受的。
从低位往高位计数。定义状态函数 \(f_{x,y}\) 为考虑完二进制 \([0,x]\) 这些位,它们求和之后等于 \(n-2^k-1\) 保留二进制 \([0,x]\) 这些位后加上 \(2^{x+1}y\) 的贡献和。对于转移:
- 枚举 \(s'_{x}+\sum\limits_{i=0}^{\min(k,x)}s_{i,x-i} = z\) 再枚举 \(y\)。那么第 \(x\) 位实际上是 \((z+y)\bmod 2\)。要求 \((z+y)\bmod 2\) 与 \(n-2^k-1\) 二进制下第 \(x\) 位相同。有 \(f_{x,\lfloor\frac{z+y}{2}\rfloor}\gets f_{x-1,y}(g_{x,z}+g_{x,z-1})\)。其中 \(g_{x,z}\) 为 \(\sum\limits_{i=0}^{\min(k,x)}s_{i,x-i} = z\) 时 \(\prod\limits_{i=0}^{\min(k,x)}\frac{1}{2^{2^{(x-i)s_{i,x-i}}}}\) 之和,这个暴力背包。
最后对于一个 \(k\) 的贡献就是 \(f_{V,0}\times \frac{1}{2^k}\)。时间复杂度 \(O(TV^4)\),其中 \(V=\log n\)。
2026.9.21
CF1830D Mex Tree
一棵树的价值为:
先给树按照深度的奇偶性染色。记 \(cnt\) 为奇数深度的点数,那么答案不会小于 \(n(n+1)-\min(cnt,n-cnt)-n\)。
定义状态函数 \(f_{u,x,0/1}\) 表示考虑 \(u\) 为根子树,和 \(u\) 颜色相同的连通块大小为 \(x\) 且 \(u\) 的颜色是黑或白的最小代价。显然 \(x \le \min(siz_u, 2\sqrt{n})\)。
暴力背包时间复杂度 \(O(n\sqrt{n})\)。
P16319 [ICPC 2023 Jinan R] 铁路环游
定义状态函数 \(f_{i,j}\) 为前 \(i\) 个,铺了 \(j\) 条铁路的最大得分。有:
- \(f_{i,j}\gets f_{i-1,j}\)。
- \(f_{i,j}\gets f_{i-k,j-k}+w(i-k+1,i)\)。其中 \(w(l,r)\) 为被 \([l,r]\) 包含的区间得分和。
换维,\(f_{i,j}\) 为前 \(i\) 个,铺了 \(i+j\) 条铁路的最大得分。有:
- \(f_{i,j}\gets f_{i-1,j+1}\)。
- \(f_{i,j}\gets f_{i-k,j}+w(i-k+1,i)\)。
记 \(g_{i,j} = f_{i,j}+w(i+1,u)\),其中 \(u\) 为当前转移点。那么每次相当于对一个 \(R = i\) 的区间 \([L,R]\),将 \(x\in [1,L-1]\) 的 \(g_{x,*}\) 都增加 \(v\)。如果令 \(\delta_x\) 为 \(g_{x,*}\) 在这一轮的增加量,那么 \(\delta_x \ge \delta_{x+1}\)。那么对于一个 \(g_{x,k}\),若存在 \(y < x\land g_{y,k}\ge g_{x,k}\),则 \(g_{x,k}\) 不可能在之后用来转移。
如果能对每个 \(k\) 维护出 \(g_{x,k}\) 的单调栈,那么转移就是 \(O(1)\) 的了。
对每个 \(k\),维护单调栈的差分。记为 \((p_i,d_i)\) 为单调栈中第 \(i\) 个元素在原序列的下标,\(d_i = g_{p_i,k}-g_{p_{i-1},k}\)。每次将 \([1,L-1]\) 的 \(g_{x,k}\) 增加 \(v\),相当于执行:
- \(d_1 \gets d_1 + v\)。
- 找到最大的 \(i\),使得 \(p_i \le L-1\)。若 \(d_{i+1}-v \le 0\),则将 \(d_{i+2}\) 修改成 \(d_{i+2}+d_{i+1}-v\),并删去 \((p_{i+1},d_{i+1})\)。重复执行此过程,直到 \(d_{i+1}-v>0\)。此时将 \(d_{i+1}\) 修改成 \(d_{i+1}-v\)。
并查集维护每个点前面第一个在栈中的元素位置即可。时间复杂度 \(O(n(n+m)\alpha(n))\) 或 \(O(n(n+m)\log n)\)。
QOJ5308 RPG职业联赛
设输出、辅助和增益分别是 \(1,2,3\)。
先二分答案 \(t\)。
考虑建立网络流模型:
- 右部点为 \(\{1\},\{2\},\{3\},\{1,2\}\)。每个点向超级汇点连容量为 \(t\),费用为 \(0\) 的边。这样只要最后所有都顶满了,就说明 \(1,2,3\) 恰好够 \(t\) 组每组一个,且剩下 \(1,2\) 能分进 \(t\) 组中。
- 左部点为 \(i\),表示一名玩家。\(i\) 向是 \(S_i\) 的子集且是右部点的点连容量为 \(1\),费用为 \(0\) 的边。
- 超级源点向每个左部点 \(i\) 连容量为 \(1\),费用为 \(p_i\) 的边。流这条就说明选这个玩家。
显然,只要最后最大流为 \(4x\),就说明可以分的组数不小于 \(x\),且分 \(x\) 组时费用就是最小费用最大流。
考虑先把组数求出来。发现此时代价是不重要的,所以对于 \(S_i\) 相同的点可以缩在一起。
将左右部点交换一下,变成判断一张有 \(4\) 个左部点,\(7\) 个右部点的带权二分图是否存在完美匹配。根据 Hall 定理,等价于 \(\min(\sum\limits_{x\in N(S)}^{}v_x-\sum\limits_{x\in S}^{}v_x)\ge 0\)。而 \(\sum\limits_{x\in S}^{}v_x = |S|\times t\),所以等价于对所有 \(S\),均有 \(\sum\limits_{x\in N(S)}^{}v_x \ge |S|\times t\)。
那么最大组数 \(t\) 满足:\(t = \min\limits_{ S}^{} \lfloor\frac{\sum\limits_{x\in N(S)}^{}v_x}{|S|}\rfloor\)。
再考虑求最小代价:先把所有的都选上,再从大到小删玩家。显然,只要删除之后最大组数仍为 \(t\) 就可以删除。
最后考虑单点修改。分两种情况:
- 当前玩家被选了。答案会变当且仅当将他和一个没被选的玩家替换。枚举这个没被选的玩家的 \(S\),显然只会选满足 \(S_i = S\) 中,\(p_i\) 最小的那个。
- 当前玩家没被选。同理,枚举替换玩家的 \(S\),选 \(p_i\) 最大的那个。
怎么写都能过。复杂度 \(O(m^22^kq\log n),k=4,m=7\)。也可以做到 \(O(q\log n)\)。
QOJ5440 P-P-Palindrome
注意到 \((P,Q)\) 合法当且仅当 \(P,Q\) 的最小回文循环节相同。
PAM 找到每个字符串的所有回文子串,再对每个回文子串找最小回文循环节即可。
时间复杂度 \(O(n\log V)\)。
2029.9.23
P7220 [JOISC 2020] 掃除
先考虑 Sub3 怎么做。
不难注意到,任意次修改后仍然满足 \(x_i \le x_{i+1},y_i \ge y_{i+1}\)。这样每次都是一个区间覆盖了。时间复杂度 \(O(n\log n)\)。
再考虑 Sub4 怎么做。
假设只有一个点不满足 \(x_i \le x_{i+1},y_i\ge y_{i+1}\) 的限制。注意到在这个点第一次被推后,整个序列就满足 \(x_i \le x_{i+1},y_i \ge y_{i+1}\) 了(排序后)。
拓展到多个点也一样。则考虑在每个点第一被推之后再加入这个点。此时就变成带插入的 Sub3 了。平衡树维护插入做到 \(O(n\log n)\)。
最后考虑原题怎么做。问题在于操作序列不同时无法像 Sub4 那样做。那么对操作线段树分治,加点的时间由于是一个时间点所以可以往上传到它的 \(O(\log n)\) 个祖先时间区间中。那么就变成 \(O(k_i)\) 个点的 Sub4 了,有 \(\sum k_i = O(n\log n)\)。
复杂度 \(O(n\log^2 n)\)。
2026.9.24
QOJ964 Excluded Min
先考虑 \(q=1\) 怎么做。
从小到大枚举 \(x\),并维护 \(cnt_x\) 表示让 \([0,x]\) 都在 \(S\) 中出现且只考虑 \(a_i\in [0,x]\) 时剩下或差 \(cnt_x\) 个数。
记 \(c_x\) 为 \(x\) 在 \(a\) 中出现次数。那么对于 \(x\to x+1\),有 \(cnt_{x+1}=cnt_x + c_{x+1}-1\)。
最后答案就是最大的 \(x\),使得 \(cnt_{x-1}\ge 0\)。
再考虑 \(q > 1\) 怎么做。
从大到小枚举 \(x\),动态维护 \(f(S) = \sum\limits_{i\in S}^{}[a_i < x]\)。那么答案为 \(x\) 的区间 \([l,r]\) 就是那些满足 \(f([l,r])\ge x\) 且没有被删除的区间,将这些区间删除再 \(x\gets x-1\) 就可以得到所有答案了。
对于 \(f(S)\),有 \(f(S)=f'(S)-\sum\limits_{i\in S}^{}[a_i = x]\)。枚举 \(x\) 后再枚举 \(a_i = x\) 的位置 \(i\) 是容易的。唯一不好处理的是我们要对所有 \(l \le i \le r\) 的区间 \([l,r]\) 对应 \(f([l,r])\) 减去 \(1\)。
发现当存在两个区间 \([l_1,r_1]\subseteq [l_2,r_2]\) 时,\([l_1,r_1]\) 的答案一定不大于 \([l_2,r_2]\) 的答案。
那么我们只保留答案可能为 \(x\) 的区间(即不存在一个包含它的区间还没被删掉),每次确定一个区间的答案后将新的答案可能为 \(x\) 的区间再加进来。这样将这些保留下来的区间按照 \(l\) 升序排序后,\(r\) 就也是升序的了。那么操作变成对一个区间 \(-1\),可以维护。
具体的,需要维护:
- 因为 \(l,r\) 严格单增,所以可以将一个区间映射到 \(l\) 上。则需要维护最后一个 \(l \le pos\) 的位置,第一个 \(r\ge pos\) 的位置。用 set 维护。
- 因为新加入的区间要查询一遍 \(f([l,r])\),所以需要另一棵线段树(树状数组)维护区间中 \(a_i < x\) 的数量。然后是在 \(l\) 处单点修改,用线段树维护。
- 删除区间相当于每次找到 \(f([l,r])\) 的最大值,当这个最大值不小于 \(x\) 时就删除。然后继续删剩下的最大值。所以需要维护全局最大值及其位置。用线段树维护。
- 删除一个区间后要将所有新的区间加进来。不妨设当前删除的区间为 \([l,r]\)。按照 \(l\) 升序排序后,记 \(l'\) 为排在 \([l,r]\) 后一个区间的左端点(没有则为 \(n+1\))。这个可以拿 set 维护。考虑从小到大枚举加入到新区间的 \(L\),首先需要保证 \(L\in [l,l'-1]\)。再维护前面加入区间中 \(R\) 的最大值 \(r_{max}\),初始为排在 \([l,r]\) 前一个区间的右端点(没有则为 \(0\))。显然,对于一个 \(L\) 加入到区间 \([L,R]\) 一定是右端点最大的那个,且满足 \(R > r_{max}\)。然后更新 \(r_{max}\gets R,L\gets L+1\) 即可。这个过程可以放到线段树上。
整体时间复杂度 \(O((n+q)\log n)\)。
CF1672I PermutationForces
把 \(i,p_i\) 看成两个序列 \(a_{1\sim n},b_{1\sim n}\)。则 \(|i-p_i|\) 可以描述成 \(|a_i-b_i|\)。
对于一次操作 \(i\):
- \(s\gets \max(s,|a_i-b_i|)\)。
- 删除点对 \((a_i,b_i)\)。
- 将 \(b_j > b_i\) 的 \(b_j\) 减 \(1\)。
- 将 \(a_j > a_i\) 的 \(a_j\) 减 \(1\)。
考虑寻找性质,如果已知 \(s\) 怎么判定是否存在合法操作。
假设点对 \((a,b)\) 在上一个时刻满足 \(|a-b|\le s\)。观察这次操作后 \((a,b)\) 的变化:
- 这次选的就是 \((a,b)\)。被删除了。
- 这次选的不是 \((a,b)\)。不妨设选的是 \((a',b')\),首先满足 \(|a'-b'|\le s\)。分类讨论:
- \(a < a', b > b'\)。\((a,b)\to (a,b-1)\)。
- 若 \(|a-b|<s\),则 \(|a-(b-1)|\le s\)。
- 若 \(|a-b|=s\),且 \(b = a+s\)。则 \(|a-(b-1)| = |a-(a+s-1)| \le s\)。
- 若 \(|a-b|=s\),且 \(a=b+s\)。则 \(a' > b+s > b > b'\)。此时 \(|a'-b'|>s\),矛盾。
- \(a > a', b < b'\)。\((a,b)\to (a-1,b)\)。同理可知 \(|(a-1)-b|\le s\)。
- \(a > a', b > b'\)。\((a-b)\to (a-1,b-1)\)。则 \(|(a-1)-(b-1)|=|a-b|\le s\)。
- \(a \le a', b\le b'\)。不变,满足 \(|a-b|\le s\)。
- \(a < a', b > b'\)。\((a,b)\to (a,b-1)\)。
由此得到一个简单的性质:
- 若 \((a,b)\) 在某时刻满足 \(|a-b|\le s\),则其在之后任意时刻都满足 \(|a-b|\le s\)。
那如果 \(|a-b|> s\) 呢?依旧设选的是 \((a',b')\),分类讨论:
- \(a < a' ,b > b'\)。\((a,b)\to (a,b-1)\)。
- \(a > b+s\)。则 \(a’ > b+s > b > b'\)。矛盾。
- \(b > a + s\)。则 \(|a-(b-1)| = b-1-a < |a-b|\)。
- \(a > a', b < b'\)。\((a,b)\to (a-1,b)\)。
- \(b > a + s\)。矛盾。
- \(a > b+s\)。则 \(|(a-1)-b| = a-1-b < |a-b|\)。
- \(a > a', b > b'\)。\((a,b)\to (a-1,b-1)\)。则 \(|(a-1)-(b-1)|=|a-b|\)。
- \(a\le a', b\le b'\)。不变。
由此得到另一个简单的性质:
- 若 \((a,b)\) 在当前时刻满足 \(|a-b|>s\),则其在下一次操作之后不会变大。
由这两个结论就可以得到一个比较简单的贪心:
- 每次将所有满足 \(|a-b|\le s\) 的点对 \((a,b)\) 删去并更新其它点对 \((a_j,b_j)\)。存在合法方案当且仅当最后所有点对都能被删去。
这个直接做是 \(O(n^2\log n)\) 的,考虑优化。
问题相当于维护所有 \(|a-b|\le s\) 的点对 \((a,b)\)。支持将 \(a_j > a\) 的 \(a_j\) 减去 \(1\),将 \(b_j > b\) 的 \(b_j\) 减去 \(1\)。
因为对于任意两个点 \((a_i,b_i),(a_j,b_j)\),\(a_i,a_j\) 的偏序关系,\(b_i,b_j\) 的偏序关系都是不变的。那么我们就不用在意 \(a,b\) 具体值了。问题变成:
- 维护 \(f(i) = |a_i - b_i|\),初始 \(f(i) = |i-p_i|\)。
- 找到一个还没被删除的点 \(i\),满足 \(f(i)\le s\)。执行以下操作:
- 对所有没被删除的 \(j\)。\(f(j)\gets f(j)-1\)。
- 对 \(j\in [i+1,n]\land p_j \in [p_i+1,n]\) 且 \(j\) 没被删除。\(f(j)\gets f(j)+1\)。
- 对 \(j\in [1,i-1]\land p_j \in [1,p_i-1]\) 且 \(j\) 没被删除。\(f(j)\gets f(j)+1\)。
这样由于 \(s \ge 0\),且有前面两个性质,那么当某个 \(f(j) \le s\) 的 \(j\) 更新出错也不会影响结果(只需要保证 \(f(j)>s\) 时更新对了就行)。
将 \(i < p_i\) 的点和 \(i \ge p_i\) 的点分开考虑。以 \(i < p_i\) 的点举例。
注意到对于 \((i,p_i),(j,p_j)\),如果 \(i < j ,p_i > p_j\),那么任意时刻 \(f(i) \ge f(j)\)。
那么保留可能被删除的点,按照第一维从小到大排序后就满足 \(i < j,p_i < p_j\) 了。这样操作就是区间操作了。
需要维护:
- \(f(i)\) 的最小值及其位置。
- 对区间的 \(f\) 值减 \(1\)。
- 加入所有满足:$ i<j,p_i>p_j$ 的 \((j,p_j)\) 都被删去了的点对 \((i,p_i)\)。此时 \(f(i)\) 等于 \(|i-p_i|\) 减去 \(i<j,p_i>p_j\) 的 \(j\) 数量。
这样 \(i\) 向 \(i>j,p_i<p_j\) 的 \(j\) 连边得到 DAG。按照拓扑序加入点就是对的(因为每个 \(j\) 加入时一定满足 \(i>j,p_i<p_j\) 的 \(i\) 删完了)。用 CDQ 优化建图即可。
维护 \(f(i)\) 最小值及其位置,对区间 \(f\) 值减 \(1\) 可以用线段树。
建图时间复杂度 \(O(n\log n)\),点数 \(O(n\log n)\) 但有用点数还是 \(O(n)\)。对于一个 \(s\) 的判定 \(O(n\log n)\)。那么整体复杂度就是 \(O(n\log^2 n)\) 的。
2026.9.25
P5521 [yLOI2019] 梅深不见冬
定义状态函数 \(f_{u}\) 为在 \(u\) 处放 \(w_u\) 朵梅花时需要的最小梅花数量。
设遍历子树的顺序为 \(v_1,v_2,\dots,v_k\)。问题相当于是最小化 \(\max\limits_{i=1}^{k}(f_{v_i} + \sum\limits_{j<i}w_{v_j})\)。
考虑邻项交换。有 \(\max(f_{i},w_i+f_{i+1})<\max(f_{i+1},w_{i+1}+f_i)\)。等价于 \(f_{i}-w_i > f_{i+1}-w_{i+1}\)。
那么按照 \(f_{v}-w_v\) 从大到小排序即可。
复杂度 \(O(n\log n)\)。
P11328 [NOISG 2022 Finals] Gym Badges
先考虑确定参加某些比赛时,该如何排列。
假设排列后的序列为 \(L_{1\dots k},X_{1\dots k}\)。那么对于 \(i\),需要满足 \(L_i -\sum\limits_{j\le i}^{}X_j \ge 0\) 才能保证获得这个徽章。
问题变成最大化 \(\min(L_i - \sum\limits_{j\le i}^{}X_j)\)。
邻项交换,\(\min(L_i,L_{i+1}-X_i)> \min(L_{i+1},L_{i}-X_{i+1})\)。等价于 \(L_i + X_i < L_{i+1}+X_{i+1}\)。
那么先给序列按照 \(L_{i}+X_i\) 升序排序。
然后再反悔贪心即可。
2026.9.26
CF2267G New LRT
拆贡献。
枚举中途的一条边 \(i\to (i+x)\),它产生的贡献为 \(c_x\)。因为 \(i\) 是不重要的,所以路径可以看作从 \(0\) 走到 \(n-x\),并在中途停顿一下(也就是 \(i\to i\) 实际上表示 \(i\to (i+x)\))。记这个方案数为 \(g(n-x)\),则答案为 \(\sum\limits_{m \text{ AND } x = x \land x\ge 1}^{}g(n-x)c_x\)。
因为每一步都满足 \(m\text{ AND }x = x\),所以对于 \(x\) 的二进制分解 \(x = 2^{y_1}+2^{y_2}\dots +2^{y_k}\),一定有 \(m\text{ AND } 2^{y_i} = 2^{y_i}\)。那么枚举 \(x\) 就可以变成枚举 \(2^{y_i}\) 了。
具体的,\(x = 2^{y_1}+2^{y_2}\dots +2^{y_k}\) 时按照 \(y\) 升序表示。这样一条路径 \(0\to x\to y\to z\to \dots\) 就可以表示成若干段,每段是一个递增的 \(2\) 的幂次序列。
定义状态函数 \(f_{i,j,0/1}\) 为当前和为 \(i\),最后一段最后一个幂次是 \(2^j\),且中途是否停顿过的方案数。记 \(s(n,k)\) 为 \(n\) 二进制下第 \(k\) 位的值。分情况转移:
- 在最后一段后面加入幂次。\(f_{i,j,c}\gets f_{i-2^j,k,c}[k < j \land s(m,j)=1]\)。
- 新开一段。\(f_{i,j,c}\gets f_{i-2^j,k,c}[s(m,j)=1],f_{i,j,1}\gets f_{i-2^j,k,0}[s(m,j)=1]\)。
初始化 \(f_{2^j,j,0}=[s(m,j)=1], f_{2^j,j,1}=2[s(m,j)=1]\)。
最后对于 \(g(x)\),有 \(g(x) = \sum\limits_{j}^{}f_{x,j,1}\)。特别的,\(g(0)=1\)。
时间复杂度 \(O(n\log V)\)。
P7831 [CCO 2021] Travelling Merchant
按照 \(r\) 从大到小删环上边 \((u,v,r,p)\)。
定义状态函数 \(f_{u}\) 为从 \(u\) 开始的最小初始资产。
考虑删这条边之后的图。对于一个点 \(i\),如果它从此刻开始就走不到环,说明之后都不可能更新 \(f_{i}\) 了,此时按照拓扑序转移 \(f_i\) 就是对的,因为 \(i\) 的所有出边都转移完了。有 \(f_{i}\gets \max(r,f_{j}-p)\),然后把这些非环上边删掉。
而对于 \(f_{u}\),因为 \(r\) 是整张图边权最大值,所以只要初始资产不小于 \(r\) 就可以在环上走。\(f_{u}\gets r\)。
时间复杂度 \(O(n+m)\)。
CF436E Cardboard Box
每个点有 \(3\) 种状态 \(0,1,2\)。
考虑每次将星星数增加 \(1\),并反悔贪心。分情况讨论:
- \(0\to 1\)。选择状态为 \(0\) 的关卡中 \(a\) 最小的那个。
- \(0\to 2,1\to 0\)。选择状态为 \(0\) 的关卡中 \(b\) 最小的那个和状态为 \(1\) 的关卡中 \(a\) 最大的那个。
- \(0\to 2, 2\to 1\)。选择状态为 \(0\) 的关卡中 \(b\) 最小的那个和状态为 \(2\) 的关卡中 \(b-a\) 最大的那个。
- \(1\to 2\)。选择状态为 \(1\) 的关卡中 \(b-a\) 最小的那个。
时间复杂度 \(O(n\log n)\)。
P2048 [NOI2010] 超级钢琴
定义 \(f(x,l,r)\) 为 \((\max\limits_{i=l}^{r}s_{i})-s_{x}\)。
然后贪心即可。初始加入所有 \(f(i,i+L,\min(n,i+R))\),每次拿一个最大的出来。设它为 \(f(x,l,r)\),且最大值在 \(pos\)。那么再加入 \(f(x,l,pos-1),f(x,pos+1,r)\) 即可。
时间复杂度 \(O(k\log n)\)。
P5829 【模板】失配树
记 \(fail_i\) 为 \(s[1:i]\) 的 \(\text{Border}\)。那么 \(i\to fail_i\) 后任意两个前缀的公共 \(\text{Border}\) 就是树上 \(\text{lca}\) 了。
时间复杂度 \(O(n\log n)\)。
P4555 [国家集训队] 最长双回文串
先求出以每个点为中心时最长回文串长度。
再维护出 \(f(i),g(i)\) 分别表示 \(i\) 为某个回文串右端点或左端点时,回文串长度的最大值。
时间复杂度 \(O(n)\)。
CF1483F Exam
把 fail 树建出来。
枚举字符串 \(s_i\),记 \(pos_{x}\) 为 \(s_i[1:x]\) 在 fail 树上的位置。那么对于 \(pos_x\) 到根路径上的所有字符串 \(s_j\) 来说,\(j\) 可能满足条件当且仅当 \(s_j\) 所在位置到 \(pos_x\) 中不存在其它任意一个字符串 \(s_k\)。显然,这样的 \(j\) 就是 \(pos_x\) 到根路径上遇到的第一个字符串。
对于每个前缀都找出来这样一个 \(j\)。发现只有 \(j\) 的出现次数与它实际上在 \(s_i\) 中出现次数相同时才会贡献 \(1\)。树状数组维护即可。
时间复杂度 \(O(n\log n)\)。
P2414 [NOI2011] 阿狸的打字机
把 fail 树建出来。
记 \(pos_x\) 为 \(s_x\) 在 fail 树上的位置。
记 \([L_i,R_i]\) 为第 \(i\) 次操作打下字符后得到的字符串是 \([L_i,R_i]\) 这些打印的字符串的前缀, \(p_i\) 为这个字符串在 fail 树上的位置。
那么一个询问 \((x,y)\) 相当于是查询有多少个 \(i\),满足 \(y\in [L_i,R_i]\) 且 \(p_i\) 是 \(pos_x\) 子树中的点。
差分一下再扫一遍就行。时间复杂度 \(O(n\log n)\)。
P5840 [COCI 2014/2015 #5] Divljak
对 \(S\) 建 fail 树。记 \(pos_i\) 为 \(S_i\) 的结尾在 fail 树上的位置。
加入一个字符串 \(P\)。枚举 \(P\) 的所有前缀 \(P[1:i]\),记 \(p_i\) 为 \(P[1:i]\) 在 fail 树上的位置。那么当 \(pos_i\) 在某个 \(p_j\) 到根的路径上时,\(S_i\) 就是 \(P\) 的子串。
问题变成给定 \(|P|\) 条点到根的路径,要对这些路径并中的点 \(+1\)。
按 dfs 序排序之后先给每个点到根路径 \(+1\),再对相邻两个的 \(\text{lca}\) \(-1\) 就行了。
时间复杂度 \(O(V\log V)\)。
P5334 [JSOI2019] 节日庆典
考虑对每个前缀 \(T[1:r]\) 维护可能成为最小字典序的起点。
对于相邻两个可能的起点 \(x,y(x<y)\),应当满足:
- \(T[y:r]\) 是 \(T[x:r]\) 的前缀。否则它们一定能比较出大小,字典序大的那个一定不可能成为起点。
- \(r - y + 1 < y-x\)。若 \(r - y + 1 \ge y-x\),则 \(T[y:r]\) 可以表示成 \(AB\),\(T[x:r]\) 近似可以表示成 \(AAB\)。拼接上一个字符串 \(C\) 后如果 \(y\) 是起点则 \(ABC < AABC\),也就是 \(BC <ABC\)。那么 \(BC<ABC<AABC\),存在更小的起点。故 \(y\) 不可能是起点。
由条件 \(2\),可知任意字符串 \(S\) 中可能成为最小字典序的起点只有 \(O(\log |S|)\) 个。
现在来维护这些可能的起点。
首先加入 \(r\),从后往前枚举 \(T[1:r-1]\) 中可能的起点。不妨设现在加入起点 \(x\),上一个起点为 \(y\):
- \(T[y:r]\) 不是 \(T[x:r]\) 前缀。比较二者大小。若 \(x < y\),则弹出 \(y\) 并继续和上一个起点比较;若 \(x>y\),则 \(x\) 不可能成为起点。
- \(T[y:r]\) 是 \(T[x:r]\) 前缀。若 \(r - y + 1 \ge y-x\),则弹出 \(y\) 并继续和上一个起点比较;若 \(r-y+1<y-x\) 则加入 \(x\)。
这样对于一个 \(r\),得到了 \(O(\log n)\) 个可能成为起点的位置 \(x\)。
从小到大枚举这些位置 \(x\),记 \(y\) 为之前所有位置中最优的那个。那么 \(x\) 比 \(y\) 优当且仅当 \(T[x:r]+T[1:x-1] < T[y:r]+T[1:y-1]\)。
因为 \(T[x:r]\) 是 \(T[y:r]\) 的前缀,所以只需要 \(T[1:x-1]<T[y + (r - x + 1):r]+T[1:y-1]\)。
先找出 \(T[1:|T|]\) 和 \(T[y + (r - x+1):|T|]\) 的 \(\text{LCP}\),设 \(\text{LCP}\) 为 \(T[1:pos]\)。分情况讨论:
- \(pos < x-y\)。等价于 \(T_{pos+1}<T_{(y+(r-x+1))+pos}\)。
- \(pos \ge x-y\)。说明 \(T[1:x-y] = T[y+(r-x+1):r]\)。等价于 \(T[x-y+1:x-1]<T[1:y-1]\)。再找出 \(T[1:|T|]\) 和 \(T[x-y+1:|T|]\) 的 \(\text{LCP}\),设为 \(T[1:pos']\)。那么:
- \(pos' < y-1\)。等价于 \(T_{(x-y+1)+pos'}<T_{pos'+1}\)。
- \(pos'\ge y-1\)。说明二者相同,\(x\) 不比 \(y\) 优。
求 \(T[1:|T|]\) 和 \(T[i:|T|]\) 的 \(\text{LCP}\) 用 Z 函数即可。时间复杂度 \(O(n\log n)\)。
AT_arc058_a [ARC058C] こだわり者いろはちゃん
暴力。
2026.9.27
P12923 [POI 2021/2022 R3] 模板 2 / Szablon 2
先考虑判断 \(s[:i]\) 是否合法。
贪心地拼,设当前 \(s[:x]\) 都拼完了。那么找到 \([1,x+1]\) 中最大的 \(y\),使得 \(s[y:y+i-1]=s[1:i]\) 或 \(s[y:y+i-1]=\text{rev}(s[1:i])\),然后 \(x\gets y+i-1\)。
设第 \(i\) 次拼的区间为 \([l_i,r_i]\),显然不存在 \([l_i,r_i]\cap [l_{i+2},r_{i+2}]\not= \emptyset\)。因为如果 \([l_i,r_i]\cap [l_{i+2},r_{i+2}]\not= \emptyset\),那么 \([l_{i+1},r_{i+1}]\) 是无用的,与贪心过程矛盾。
也就是说,每拼 \(2\) 次就一定拼 \(i\) 这么长,那么就只会拼 \(O(\frac{|s|}{i})\) 次。
那么枚举 \(i\),暴力拼的复杂度就是 \(O(|s|\log |s|)\) 的。
现在考虑找到这样的 \(y\)。分情况讨论:
- \(s[y:y+i-1]=s[1:i]\)。记 \(len_i\) 为 \(s\) 与 \(s[i:]\) 的 \(\text{LCP}\) 长度。那么条件等价于 \(len_y \ge i\)。从小到大枚举 \(i\),维护 \(pre_{x}\) 为 \(x\) 前面第一个 \(len_y\ge i\) 的 \(y\) 值。那么每次删去所有 \(len_y =i-1\) 的位置 \(y\) 时,将所有 \(pre_{x} = y\) 的都修改成 \(pre_{y-1}\),并查集即可。
- \(s[y:y+i-1] =\text{rev}(s[1:i])\)。记 \(len'_i\) 为 \(s[:i]\) 与 \(\text{rev}(s)\) 的 \(\text{LCS}\) 长度。那么等价于 \(len'_{y+i-1}\ge i\)。还是维护 \(pre'_x\) 为 \(x\) 前面第一个 \(len'_y\ge i\) 的 \(y\) 值。
时间复杂度 \(O(|s|\log |s|\alpha (|s|))\)。
P12763 [POI 2018 R2] 诗集 Book of poetry
先将 \(a_i\) 变成 \((a_i+1)\bmod s\)。
贪心地,每次拿出出现次数最大的数填。如果填了之后得到的和是 \(s-1\),且存在次大值,就替换成次大值。
时间复杂度 \(O(n\log n)\)。
P5592 美德的讲坛
先把 \(x\) 减 \(1\) 变成小于等于。
建一棵 Trie。枚举 \(x\) 二进制下高位的前缀,设当前走到 Trie 树的节点 \(u\)。分情况讨论:
- \(x\) 这一位是 \(0\)。此时要么往左走要么往右走。
- \(x\) 这一位是 \(1\)。此时还可能在左右都选一些。
那么定义状态函数 \(f(u,v)\) 为在 \(u,v\) 两个子树中选一些数满足条件时,选择的数的数量最大值。
- 对于 \(f(u,u)\)。
- \(x\) 这一位是 \(0\)。\(f(u,u)=\max(f(ls_u,ls_u),f(rs_u,rs_u))\)。
- \(x\) 这一位是 \(1\)。\(f(u,u)=\max(siz_{ls_u},siz_{rs_u},f(ls_u,rs_u))\)。
- 对于 \(f(u,v)\)(\(u\ne v\))。
- \(x\) 这一位是 \(0\)。\(f(u,v)=\max(siz_u, siz_v, f(ls_u,ls_v),f(rs_u,rs_v))\)。
- \(x\) 这一位是 \(1\)。\(f(u,v) = \max(siz_u,siz_v,f(ls(u),rs(v))+f(rs(u),ls(v)))\)。这里能直接加是因为 \(ls(u)\) 和 \(rs(v)\) 子树中任意两个多异或和都不可能大于 \(x\)(在之前一定是某一位 \(1\) 取到了 \(0\))。
特别的,如果当前位已经是最低位了,则 \(f(u,u)=siz_u, f(u,v) = siz_u+siz_v\)。
记 \(T(i)\) 为考虑到二进制第 \(i\) 位时的有效状态数,那么:
- \(T(61)=1\)。
- \(T(i) = \min(n,2T(i-1))\)。
那么直接跑一遍就是 \(O(n\log V)\) 的。
因为 Trie 上每个点最多被一个状态包含,而一次修改只会影响 \(O(\log V)\) 个点。那么加个记忆化再暴力求答案的复杂度就是 \(O((n+q)\log V)\) 的。
[ICPC 2026 Wuhan I] String Matching
对 \(t = s_i + s_j\) 分两种情况:
- \(1 \le x \le |s_i|\)。相当于 \(s_i[:x] = s_j[|s_j|-x+1:]\)。枚举 \(x\) 后哈希即可。
- \(|s_i| < x \le |s_j|\)。相当于 \(s_i = s_j[|s_j|-x+1:|s_j|-x+|s_i|],s_j[:x-|s_i|] =s_j[|s_j|-x+|s_i|:]\)。枚举 \(s_j\) 的所有 \(\text{Border}\),在 fail 树上就是查询有多少个字符串结尾。DFS 一遍即可。
- \(|s_j| < x \le |s_i|+|s_j|\)。枚举 \(s_i\) 的 \(\text{Border}\),记为 \(s_i[:y]\)。将 \(s_i[y+1:]\) 的哈希值放进去。再枚举 \(s_j\),枚举 \(\text{Border}\),记为 \(s_j[:z]\)。查询 \(s_j[:|s_j|-z]\) 的哈希值出现的次数即可。
整体时间复杂度 \(O(\sum |s_i| \log V)\)。
[ICPC 2026 Wuhan I] Believe in You
直接贪心。
[ICPC 2026 Wuhan I] Prime Game
每次变成 \(2^a 3^b\) 是不劣的。
模拟即可。
[ICPC 2026 Wuhan I] Rectangle Cutting
维护最长的长和宽即可。
到着做只需要合并。
时间复杂度 \(O(n\log n)\)。
[ICPC 2026 Wuhan I] Sequence Operations
首先如果存在某个操作 \(2\) 在操作 \(1\) 前面,答案一定是 \(\text{Yes}\)。因为操作 \(2\) 让 \(a_i > 0\),遇到后面某个操作 \(1\) 时由于 \(x > 0\) 所以 \(\text{mex}(a_i,x)=0\)。之后就全部相同了。
否则 \(c_i = 0\) 只会有最多 \(1\) 个。且它处于 \(1,2\) 操作中间。即操作序列形如 \(111\dots11 022\dots222\)。
那么暴力枚举所有可能情况。问题变成快速判断给定操作序列最终是否所有数都相同。
第一次操作 \(1\) 后值域变成 \(\{0,1,2\}\)。且无论 \(x_i\) 具体是什么,连续若干次操作 \(1\) 的变化一定是 \(0 \to (1/2) \to 0\to (1/2)\to\dots\)。
首先可以根据初始值和操作次数得到这个数是否是 \(0\)。再根据最后一次操作的 \(x_i\) 得到是 \(1\) 还是 \(2\)。
对于操作 \(2\) 直接取 \(\gcd\) 即可。
时间复杂度 \(O(n\log V)\)。
[ICPC 2026 Wuhan I] Lottery
定义 \(f_{i}\) 为抽奖代价为 \(i\) 时的期望利润。有:\(f_i = \frac{1}{n}(\sum\limits_{x=1}^{n}\max(A_x,f_{i+k}))-i\)。
当 \(i > \max(A)\) 时显然不会继续抽,有 \(f_i = \frac{1}{n}(\sum\limits_{x=1}^{n}A_x)-i\)。
按 \(A\) 升序排序之后二分即可。时间复杂度 \(O((n+V)\log n)\),其中 \(V=\max(A)\)。
特别的,\(k = 0\) 时二分答案即可。
CF2211G Rational Bubble Sort
记 \(s_i\) 为前缀和,那么一次操作 \(i\) 相当于 \(s_i\gets \frac{s_{i+1}+s_{i-1}}{2}\)。
最后要求 \(s\) 下凸。
把 \((i,s_i)\) 连起来,那么一次操作相当于将 \((i-1,s_{i-1}),(i,s_i),(i+1,s_{i+1})\) 这三个点构成的折线段拉直。
如果存在一个点 \((i,s_i)\) 位于线段 \(((0,0),(n,s_n))\) 之下,由于对于任意 \((i,j)\) 都可以将 \(k\in (i,j)\) 无限逼近 \(((i,s_i),(j,s_j))\),所以一定有解。
否则所有点都在线段 \(((0,0),(n,s_n))\) 之上。此时如果有相邻两个点都不在线段上就一定无解,因为逼近并不等于重合。反之由于 \((i-1,s_{i-1}),(i+1,s_{i+1})\) 都在线段上时一定可以让 \((i,s_i)\) 也在线段上,一定有解。
时间复杂度 \(O(n)\)。
2026.9.28
P13352 [GDCPC 2024] 腊肠披萨
因为 \(\text{LCPS}(s_i,s_j)\) 不太好直接表示,考虑简化限制并通过容斥来得到它。
一个 \(s_i\) 的前缀 \(s_i[:x]\) 可能是 \(\text{LCPS}(s_i,s_j)\),当且仅当 \(s_i[:x]=s_j[|s_j|-x+1:]\)。
对所有这样的 \(x\) 乘上它的容斥系数求和,目标为 \(C^{\text{LCPS}(s_i,s_j)} = \sum\limits_{x}^{}C^{c_x \times [s_{i}[:x]=s_j[|s_j|-x+1:]]}\)。
显然,将可能的 \(x\) 从小到大排序后,前一个一定是后一个的 \(\text{Border}\)。对于一个字符串 \(s_i\),定义 \(c_x\) 为 \(C^{x }-C^{\text{Border}(s[:x])}\)。其中 \(\text{Border}(s)\) 为字符串 \(s\) 的 \(\text{Border}\) 长度。
这样就满足等式 \(C^{\text{LCPS}(s_i,s_j)} = \sum\limits_{x}^{}C^{c_x\times [s_{i}[:x]=s_j[|s_j|-x+1:]]}\) 了。
建 fail 树。
枚举 \(s_i\) 的所有前缀 \(s_i[:x]\),记 \(s_i[:x]\) 在 fail 树上的位置为 \(pos_x\)。那么在点 \(pos_x\) 这里挂一个 \(c_x\) 表示如果一个字符串的后缀等于它,就会得到 \(c_x\) 的贡献。
再枚举 \(s_j\),记 \(pos\) 为 \(s_j\) 在 fail 树上的位置。那么所有 \(s_i\) 对 \(s_j\) 的贡献和就是 \(pos\) 到根路径中所有点的权值和。这个可以简单维护。
时间复杂度 \(O(n|\sum|)\)。
P4156 [WC2016] 论战捆竹竿
对字符串 \(S\) 求出它的所有 \(\text{Border}\)。
对于一个长度为 \(x\) 的 \(\text{Border}\),如果捆这么长,就会让字符串的长度增加 \(|S|-x\)。
设所有 \(\text{Border}\) 长度分别为 \(l_1,l_2,\dots ,l_k\)。问题变成对于所有非负整数序列 \(x_{1\sim k}\),在 \(\sum\limits_{i=1}^{k}x_i(|S|-l_i)\le w\) 时,\(\sum\limits_{i=1}^{k}x_i(|S|-l_i)\) 有多少种。
因为任意一个字符串 \(S\) 的所有 \(\text{Border}\) 一定可以分成 \(O(\log |S|)\) 个等差数列。
考虑对于每个等差数列单独更新。
不妨设这个等差数列为 \(c_i = a + (i-1)b\)。以 \(a\) 为模数连边得到一个环。因为环上 \(dis\) 最小的点一定不会更新,所以破环成链后变成前缀 \(\min\)。
而对于模数的变化,\(dis(x)\) 可以更新到 \((dis(x) + kb)\bmod b'\),也是可以直接跑一遍。
时间复杂度 \(O(T|S|\log |S|)\)。
AT_arc058_c [ARC058E] 和風いろはちゃん
容斥,那么只需要对不合法的计数。
注意到 \(X+Y+Z\le 17\),考虑状压。
具体的,把 \(X\) 看作 \(100\dots 0\),其中 \(0\) 的数量为 \(X-1\)。那么就只需要表示最后一段和不超过 \(17\) 的数了。例如 \(1,1,2,4,7\) 可以表示成 \(00111010001000000\)。
再预处理一下一个长度为 \(17\) 的二进制数能不能凑出一段 \(X,Y,Z\) 即可。
时间复杂度 \(O(2^{k}k+nk2^k),k=17\)。
AT_abc458_f [ABC458F] Critical Misread
把 ACAM 和 fail 树建出来。
那么相当于一直在 ACAM 上面走,要求不能走到一个满足 fail 树到根链上存在一个字符串 \(S_i\) 的结尾的点。
先把这些点标记为非法,记为 \(st_x = 1\)。
问题变成,从 \(0\) 开始走 \(n\) 步,要求每次走到的点都要满足 \(st_x=0\),求方案数。
矩阵快速幂优化即可。复杂度 \(O((\sum|s_i|)^3\log n)\)。
P9089 「SvR-2」Work
先考虑怎么判断一个字符串 \(T\) 是否是有意义的。
一个简单的贪心是从前往后划分,当前划分完了 \(T[:x-1]\)。那么找到最小的 \(y\ge x\),使得 \(T[x:y]\) 是某个字符串的后缀,然后将 \(T[x:y]\) 划分掉。
这个的正确性比较显然。因为如果存在某次划分 \(T[x:y]\),且 \(y\) 不是最小的那个。设最小的那个为 \(z\),因为 \(T[x:y]\) 是某个字符串后缀,所以 \(T[z+1:y]\) 也一定是这个字符串后缀。而 \(T[x:z]\) 又是合法的划分,所以可以划分成 \(T[x:z]\) 和 \(T[z+1:y]\)。然后继续调整。
对于一个字符串 \(S\),记 \(pos_i\) 为最小的 \(j\),使得 \(S[i:j]\) 是某个字符串的后缀,没有则为 \(|S|+1\)。定义状态函数 \(f_i\) 为子串的开头下标为 \(i\) 且是有意义的子串数量。转移为 \(f_{i}=f_{pos_i+1}+[pos_i\ne |S|+1]\)。
问题变成求 \(pos_i\)。对所有字符串的反串建 ACAM 和 fail 树。先找到 \(T[i:]\) 在 fail 树上的位置(到着走),记为 \(x\)。维护 \(len_i\) 为 fail 树上点 \(i\) 表示的字符串长度。那么相当于是查询 \(x\) 到根路径中,除了根以外所有点 \(len\) 的最小值。因为路径中每个点都是某个字符串后缀且是 \(T[i:]\) 的一个前缀。DFS 一遍即可。
时间复杂度 \(O((\sum |S_i|)|\sum|)\)。
注文の多い順列
直接容斥。
定义 \(G(x)\) 为钦定 \(x\) 个 \(t_i=1\) 的 \(i\) 不符合限制的方案数。那么答案为 \(\sum\limits_{x\ge 0}^{}(-1)^{x-0}\binom{x}{0}G(x)\)。
那么现在就全都是 \(\le X\) 的限制了。将 \(t_i = 1\) 的 \(X_i\) 减 \(1\),按 \(X_i\) 从小到大排序。
定义状态函数 \(f_{i,j}\) 为前 \(i\) 个数,所有 \(t=0\) 都满足条件,有 \(j\) 个 \(t=1\) 钦定不满足条件,且不管不钦定的数的方案数。
记 \(s_i\) 为前 \(i\) 个数中 \(t=0\) 的数量。分类讨论:
- \(t_i = 0\)。\(f_{i,j}=f_{i-1,j}(X_i-s_{i-1}-j) [s_{i-1}+j<X_i]\)。
- \(t_i=1\)。\(f_{i,j}=f_{i-1,j}+f_{i,j-1}(X_i-s_{i-1}-(j-1))[s_{i-1}+(j-1)<X_i]\)。
最后 \(G(x) = f_{n,x}(n-x-s_{n})!\)。
时间复杂度 \(O(n^2)\)。
gym106559B Buhăiești
先枚举 \(\text{LCP}\),再枚举 \(\text{LCP}\) 下一位的值。相当于确定了 \(A\) 的一个前缀。
记 \(s_i=\text{mex}(B_{1\sim i})\)。那么对于 \(i\) 的限制相当于是:
- 存在 \(x\in [0,s_i]\),使得 \(A_{1\sim i}\) 都不是 \(x\)。
定义状态函数 \(f_{i,j,k}\) 表示考虑完 \(A_{1\sim i}\),并且 \([0,j]\) 的数都出现过,有 \(k\) 个位置还没有确定数但一定比 \(j\) 大的方案数。
从第一个每确定的位置开始转移。
- \(f_{i,j,k}\gets f_{i-1,j,k}\times (j+1),f_{i,j,k + 1}\gets f_{i-1,j,k}\)。
- 考虑增大出现过的数的范围。首先得要求 \(A_i = j+1\)。
- \(j+1\) 在之前确定的位置中出现过。\(f_{i,j+1,k-x}\gets f'_{i,j,k}\binom{k}{x}[x\ge 0][j+1\le m]\)。
- \(j+1\) 在之前确定的位置中没出现过。\(f_{i,j+1,k-x}\gets f'_{i,j,k}\binom{k}{x}[x\ge 1][j+1\le m]\)。
最后如果 \(j\) 在之前确定的位置中出现过,\(f_{i,j-1,*}=0\)。同理在 \(j \ge s_i\) 时 \(f_{i,j,*}=0\)。
初始化 \(f_{pos,\text{mex}(A_{1\sim pos})-1,0}=1\),其中 \(pos\) 是最后一个确定的位置。
最后答案为 \(\sum f_{n,j,k}(m-j-1)^k\)。
发现其实 \(\text{LCP}\) 后面第一个数也可以放进去转移。复杂度为 \(O(n^4m)\)。
有一些细节不重要,比如情况 \(2\) 的时候可能需要单独一个数组 \(g\) 来转移而不是直接用 \(f\)。还有 \(A_{\text{LCP}+1}\) 有个特别的值域,可能需要再开一维 \(0/1\)。
被误解的 . . . 缺失
从上到下定义操作为 \(1,2,3\)。
对于一个 \(1,2,3\) 构成的序列 \(x\),考虑表示它造成的伤害。
对于 \(i\) 时刻开始时的 \(A\),有:\(A = \sum\limits_{j=1}^{i-1}c_j[x_j=3]+\sum\limits_{j=1}^{i-1}b_j(i-j)[x_j=2]\)。显然它们两个是独立的。枚举 \(i\),考虑 \(a_i,b_i,c_i\) 对伤害的贡献,有:
- \(x_i = 1\)。造成 \(a_i\) 的伤害。
- \(x_i = 2\)。造成 \(b_i\times (\sum\limits_{j=i+1}^{n}(j-i)[x_j=1])\) 的伤害。
- \(x_i = 3\)。造成 \(c_i \times (\sum\limits_{j=i+1}^{n}[x_j=1])\) 的伤害。
那么定义状态函数 \(f_{i,j,k}\) 为考虑完 \(x_{i\sim n}\),其中 \(x_u = 1\) 的 \(u\) 之和为 \(j\),有 \(k\) 个这样的 \(u\) 时伤害和的最大值。
转移为:
- \(x_i = 1\)。\(f_{i,j+i,k+1}\gets f_{i+1,j,k}+a_i\)。
- \(x_i = 2\)。\(f_{i,j,k}\gets f_{i+1,j,k}+b_i\times (j-k\times i)\)。
- \(x_i = 3\)。\(f_{i,j,k}\gets f_{i+1,j,k}+c_i\times k\)。
初始化 \(f_{n+1,0,0} = 0\)。答案为 \(\max\limits_{j,k}^{} f_{1,j,k}\)。时间复杂度 \(O(n^4)\)。

浙公网安备 33010602011771号