Loading

2026.1 重庆集训

Day1 网络流

P2762 太空飞行计划问题

考虑怎么在网络上体现 \(R_i\) 的实验器材全部解锁才能实现 \(i\)。这个模型是最大权闭合子图问题,考虑这样建图:

P2762.png

左边表示实验,右边表示器材,从 \(s\to i\) 的容量为 \(p_i\),中间的边 \(i\to j\) 容量为 \(+\infty\)\(j\to t\) 的容量 \(c_j\)。如果我们在这个网络 \(G\) 上跑最小割,那么我们令 \(S\) 中选择的实验和器材那么由于中间的容量被赋了 \(+\infty\),起到了防止被割开的作用,这样保证了 \(i\) 如果要被解锁则需要购买所有 \(R_i\)

考虑此时最小割 \(W\) 的意义,我们发现此时 \(W\) 表示 \(\min\set{ (不选择的 \sum p_i)+(选择的 -\sum c_j)}\),那么可以发现 \((\sum p_i)-W\) 就是原问题的答案。

Day3 构造/交互/?

Problem G.矩阵

考虑如何刻画 \(\gcd(x,y)=1\),我们注意到:

  1. \(\gcd(x,x+1)=1\)
  2. 素数和任何数都是互素的。

因此考虑这样一个构造:

\[\begin{bmatrix} 1 & 2 & 3 & \dots & n\\ 1+p & 2+p & 3+p & \dots & n+p\\ 1+2p & 2+2p & 3+2p & \dots & n+2p\\ \dots & \dots & \dots & \dots & \dots\\ 1+(n-1)p & 2+(n-1)p & 3+(n-1)p & \dots & n+(n-1)p \end{bmatrix} \]

其中 \(p\)最小的大于 \(n\) 的质数\(\mathrm{M}_{i,j}=j+(i-1)p\)

在这个构造中,我们发现

\[\gcd(M_{i,j},M_{i,j-1})=\gcd(j+(i-1)p,j-1+(i-1)p)=1 \\ \gcd(M_{i+1,j},M_{i,j})=\gcd(j+ip,j+(i-1)p)=\gcd(j+(i-1)p,p)=1 \]

且任意两个数都不会相同,否则等价于 \(p\le n\)\(p\) 不是指数,因此这个构造符合条件。

并且最大的数 \(n+(n-1)p\)\(p\le n+40\),因此也不会超过范围。

QOJ 9178. All-You-Can-Eat

这太难了。分类讨论一下:

1.若 \(sum\ge 600\),此时已经满足条件,IGNORE
2.若 \(w\ge 600\),此时直接抛弃所有选这个就完成了。
3.若 \(sum+w\le 1000\),此时拿这个肯定不劣,因此带上。
4.对于剩余情况,我们发现一定有 \(w\in [400,600),sum<600\)

对于情况4,考虑已经选择的物品中价值 \(\ge 400\) 的集合 \(S\),考虑找到其中 \(w_p\) 最小的物品 \(p\),如果此时有 \(w+w_p\le 1000\) 则拼起来就完成了。

否则考虑 \(w\)\(S\) 的影响,考虑这种情况:{...,501} + 500,如果我们替换为 500,则过来一个 500 时就可以拼成 \(500+500\le 1000\),如果不换就不行。因此如果 \(w<w_p\) 则用 \(w\) 替换掉 \(w_p\)

因此如果有 \(w\ge w_p\)\(w\) 没有用。否则我们选上 \(w\),并在原来的物品中贪心地挑出和 \(\le 1000\) 的物品组成新的物品集合即可。

QOJ 14333.Secret Lilies and Roses

很牛的题。先给出结论,如果我们知道了序列中 \(1\) 的个数 \(k\),那么位置 \(k\) 就是一个合法的位置。记 \(k\) 左边有 \(l_k\)\(0\),则 \(k\) 左边有 \(k-l_k\)\(1\),其右边有 \(k-(k-l_k)=l_k\)\(1\),左右 \(0,1\) 个数相同。

考虑怎么得到序列中 \(1\) 的个数。如果我们可以找到一个 \(10\) 结构的位置 \(x\),即 \(c_x=1,c_{x+1}=0\),考虑询问 \(x-1\)\(x+1\),记两次答案 \(S_1=l_{x-1}r_{x-1}=l_x(r_x+1),S_2=l_{x+1}r_{x+1}=(l_x+1)r_x\),那么我们要的 \(1\) 的个数就是 \(l-l_k+r_k=l+S_2-S_1\),因此如果我们可以找到这种结构,通过两次询问就可以得到答案。

考虑用一个非常神奇的二分来找到任意一个 \(10\) 结构。对二分区间 \([l,r]\),我们时刻保持其满足 \(l_{k-1}=1,r_{k+1}=0\),即形成 \(1[\dots]0\) 的结构,此时我们问一下 \(c_{mid}\),如果是 \(1\),那么 \([l,r]\) 区间可以往右边缩到 \([mid+1,r]\),否则可以往左缩到 \([l,mid-1]\)。直到最后 \([l,r]\) 为空,即 \(l>r\) 时,就退化成了一个 \(10\) 结构。因此总操作次数为 \(\left\lceil\log_2n\right\rceil+2\)

QOJ 14726. Restore the Array

既然涉及到异或最大值,自然考虑01 Trie这个结构来刻画。有一个很牛的观察,我们可以通过高位取反、低位不变的方式进行询问,进而得到 \(u\) 子树内的最小值,同理也可以问到最大值。因此考虑用 \(\mathrm{dfs}(dep,x)\) 表示当前走到某个子树,其深度为 \(dep\),且我们知道这个子树内有一个最值为 \(x\)\(\min\)\(\max\))时还原这棵子树内的数。根据上述观察,我们可以取反 \(x\) 高位来得到这个子树内的 \(\min\)\(\max\),然后我们将 \(dep\) 往下推直到 \(\min,\max\) 分开,然后继续往下还原即可。

void dfs(int dep,int val)
{
	if (v.size()==n || !dep) return;
	int hi=0; for (int i=29;i>=dep;i--) hi|=(1<<i);
	int x=ask(val^hi)^val^hi; //取反高位找到最小
	if (x==val) return; v.psb(x);
	while (~(x^val)>>dep&1) dep--;
	dfs(dep,x), dfs(dep,val);
}

Day4 计数1

[ARC102E] Stop. Otherwise...

若要求不等于 \(x\),则非法的骰子对会形如 \((p,x-p)\),不妨设 \(p\le x-p\),将这样的非法形态称为一个对子,则我们相当于要对恰好有 \(0\) 种对子的局面计数,这使我们联想到二项式反演,转而求出 \(G(i)\) 表示至少有 \(i\) 种对子的局面个数,然后有 \(ans=\sum\limits_{i=0} (-1)^i G(i)\)

考虑怎么求 \(G(i)\)。先钦定我们选择的 \(i\) 对子,对子需要满足 \(1\le p\le x-p\le K\),解得 \(p\in [max(1,x-K),\left\lfloor\frac{x}{2}\right\rfloor]\),因此总共有 \(tot=\left\lfloor\frac{x}{2}\right\rfloor-max(1,x-K)+1\) 种对子可供选择,因此选对子有 \(\binom{tot}{i}\) 种选择方案。而对于剩下的 \((n-2i)\) 个没有钦定的牌,其可以任意分配点数,由于互不区分,可以简单插板,不难得到方案数就是 \(\binom{n-2i+k-1}{k-1}\)。因此:

\[G(i)=\binom{tot}{i}\binom{n-2i+k-1}{k-1} \]

于是 \(O(n^2)\) 解决问题。

P6076 [JSOI2015] 染色问题

二项式定理复习题。

\(f_i\) 表示满足至多 \(i\) 个限制,\(g_i\) 表示满足恰好 \(i\) 个限制,则我们有:

\[g_n=\sum_{0\le k\le n} (-1)^{n-k}\binom{n}{k}f_k \]

运用二项式定理,我们可以逐层剥掉三个限制,从颜色开始,考虑令 \(F(C)\) 表示使用了至多 \(C\) 个颜色并满足条件 \(1,2\) 的方案数,那么我们有:

\[ans=\sum_{0\le C\le K} (-1)^{K-C}\binom{K}{C}F(C) \]

\(F(C)\) 再次考虑剥掉"列全部要填"的限制,用 \(G(C,j)\) 表示使用至多 \(C\) 种颜色,填了至多 \(j\) 列的方案数,那么我们有:

\[F(C)=\sum_{0\le j\le m} (-1)^{m-j}\binom{m}{j}G(C,j) \]

再次审视 \(G(C,j)\),我们需要继续剥掉行的限制,用 \(\omega(C,j,i)\) 表示使用至多 \(C\) 种颜色,填了至多 \(j\) 列,填了至多 \(i\) 行的方案数,同理有:

\[G(C,j)=\sum_{0\le i\le n}(-1)^{n-i}\binom{n}{i}\omega(C,j,i) \]

哦我们发现 \(\omega(C,j,i)\) 的意义似乎已经非常明了了,取出这 \(i\)\(j\) 列的交点,形成了一个新的 \(i\times j\) 的棋盘,\(\omega\) 的意义其实就是这个棋盘的每个位置可以不填或是填 \(1\sim C\) 中的任意一个数,因此可以得到 \(\omega(C,j,i)=(C+1)^{ij}\)

如果这样直接算就可以做到 \(O(nmC)\) 了,不过我们可以做得更好,将 \(\omega\) 带入 \(G\) 中,运用二项式展开式:

\[\begin{aligned} G(C,j) &= \sum_{0\le i\le n}(-1)^{n-i}\binom{n}{i}(C+1)^{ij} \\ &= \sum_{0\le i\le n}(-1)^{n-i}\binom{n}{i}[(C+1)^j]^i \\ &=[(C+1)^j-1]^n \end{aligned} \]

然后就可以 \(O(mC)\) 解决此题了。

P8990 [北大集训 2021] 小明的树

点边容斥+Ad-hoc

对于"美丽"的定义还是太繁琐了,能不能简化?如果点 \(u\) 是白色的,则其子树是白色的,这其实等价于任意一个黑色点都没有白色祖先,换言之,合法当且仅当黑色点连通。那这个条件就很容易刻画了,考虑点边容斥,令 \(f_i=i-E(\set{a_1,a_2,\dots,a_i})\)\(g_{i}=(n-i)-E(\set{a_{i+1},a_{i+2},\dots,a_n})\),即用 \(f_i,g_i\) 分别表示 \(i\) 时刻白/黑点形成的连通块个数。则贡献可以表示为 \(\sum\limits_{i=1}^{n-1} [g_i=1]f_i\),,相当于要对 \(g_i\) 取到最小值的 \(f_i\) 计数。可以简单使用线段树维护,支持区间 \(f_i,g_i\) 加即可支持加边。

时间复杂度 \(O(q\log n)\)

计数2

P2290 [HNOI2004] 树的计数

Prufer序列 练习题

根据条件,这相当于prufer序列中恰好有 \((d_i-1)\)\(i\),因此我们特判掉 \(\sum d_i-1\ne n-2\) 的不合法情况以及 \(n=1,2\) 后,这个可重排列的方案数就是树的方案数,即 \(\dfrac{(n-2)!}{\prod{(d_i-1)!}}\)

CF785D Anton and School - 2

我们可以枚举最后一个 \(\texttt{(}\) 的位置 \(i\),用 \(A,B\) 分别表示 \(i\) 前面(包括 \(i\)\(\texttt{(}\) 的个数和 \(i\) 后面 \(\texttt{)}\) 的个数,枚举 \(k\) 表示 \(i\) 前面选了几个 \(\texttt{(}\),则贡献可以表示为:

\[W=\sum_{k=0}^{\min(A-1,B-1)}\binom{A-1}{k}\binom{B}{k+1} \]

直接算是 \(O(n^2)\) 的,但是稍加变形后运用范德蒙德卷积 即可得到:

\[\begin{aligned} W &= \sum_{k=0}^{\min(A-1,B-1)}\binom{A-1}{A-1-k}\binom{B}{k+1} \\ &= \sum_{k=0}^{\min(A-1,B-1)}\binom{A-1}{A-(k+1)}\binom{B}{k+1} \\ &= \boxed{\binom{A+B-1}{A}} \end{aligned} \]

于是可以直接 \(O(n)\) 随便做。

Count Triangular Sequences

进行一个容斥,升序排序后就是要对满足 \(\forall i,a_i\ge a_{i-1}+a_{i-2}\) 的序列 \(a\) 计数。注意到这和斐波那契数列 \(F\) 很像,考虑定义一个差分数组 \(c_i=a_i-a_{i-1}-a_{i-2}\),特别的 \(c_1=a_1,c_2=a_2-a_1\),有很优美的性质:

  • \(c\)\(a\) 形成了双射,对 \(a\) 计数等价于对 \(c\) 计数
  • \(c_1=a_1,a_i\ge a_{i-1}+a_{i-2}\),我们可以得到 \(c_1\ge 1,c_i\ge 0\)
  • 通过归纳我们发现有:$a_m=\sum\limits_{k=1}^m c_kF_{m-k+1} $。
  • \(F\) 是指数级增长的,因此我们可以断言 \(m\)\(O(\log n)\) 级别的。

因为需要满足的限制只有 \(a_m\le n\),所以 \(a_m=\sum\limits_{k=1}^m c_kF_{m-k+1}=c_1F_m+c_2F_{m-1}+\sum\limits_{k=3}^mc_kF_{m-k+1}\le n\),这个形式与对着 \(F\) 作背包几乎没有任何区别。那么直接跑背包对吗?注意到我们进行了升序排序,虽然对于 \(i>2\) 必然有 \(a_i\ne a_{i-1}\),但是有可能出现 \(a_1=a_2\) 的情况,即 \(c_2=0\)。在 \(c_2=0\) 时,对 \(a\) 任意排列的方案数是 \(\frac{m!}{2}\),而其他情况是 \(m!\)

具体的求答案的流程是,对 \(F\) 的前 \(m\) 项跑完全背包时,若限制目前的和为 \(j\),则我们分类一下:

  • \(j+F_m>n\),此时无法保证 \(c_1\ge 1\),直接pass

  • \(j+F_m+F_{m-1}>n\),此时可以保证 \(c_1\),但是无法保证 \(c_2\ge 1\),此时 \(c_2=0\),贡献系数为 \(\frac{m!}{2}\)

  • \(j+F_m+F_{m-1}>n\),此时 \(c_1,c_2\) 都可以保证至少有 \(1\),因此贡献系数为 \(m!\)

由于 \(m\)\(O(\log n)\) 的,因此时间复杂度为 \(O(n\log n)\)

CF708E Student's Camp

让我们刻画一下连通(合法)的状态,由于只能从左右侵蚀,所以每一层在最后会剩下一个区间 \([l_i,r_i]\),那么连通就相当于任意相邻两行都没有被切开,即 \(\forall i,[l_i,r_i]\cap [l_{i-1},r_{i-1}]\ne\varnothing\)。那么我们已经可以设计一个很naive的 \(O(n^5)\) \(\mathrm{dp}\) 了,即 \(f_{i,l,r}\) 表示考虑前 \(i\) 行,第 \(i\) 行被侵蚀成 \([l,r]\) 时合法的概率。我们有转移:

\[f_{i,l,r}=P(l,r)\times \sum_{[L,R]\cap [l,r]\ne\varnothing} f_{i-1,L,R} \]

其中 \(P(L,R)\) 表示一行在 \(k\) 天被侵蚀成 \([l,r]\) 的概率,用 \(\omega(x)\) 表示 \(k\) 天侵蚀 \(x\) 格的概率,则 \(\omega(x)=\dbinom{k}{x}p^x(1-p)^{k-x}\),则有 \(P(L,R)=\omega(L-1)\times \omega(m-R)\)

考虑如何优化,有交不好做,考虑用容斥转化成无交,\([L,R]\cap [l,r]=\varnothing \Leftrightarrow R<l\vee L>r\),即

\[f_{i,l,r}=P(l,r)\times \left(\sum_{[L,R]} f_{i-1,L,R}-\sum_{L\le R<l} f_{i-1,L,R}-\sum_{r<L\le R} f_{i-1,L,R}\right) \\ =P(l,r)\times \left[F(i-1)-L(i-1,l)-R(i-1,r)\right] \\ \]

代换掉后,我们发现答案就是 \(F(n)\)。仔细观察,其中的 \(L,R\) 定义似乎就是对称的!这也不难理解,我们可以将全部区间对称一下,这样在左边就转到了右边,据此我们可以发现 \(L(i,x)=R(i,m-x+1)\),于是可以用 \(L\) 代换掉 \(R\)

\[f_{i-1,l,r} =P(l,r)\times \left[F(i-1)-L(i-1,l)-L(i-1,m-r+1)\right] \]

直接求 \(L\) 用前缀和优化一下可以做到 \(O(n^3)\),但这还是不够。分析一下我们发现状态数量都成为了瓶颈,似乎很难优化了。不过现在 \(L\) 太复杂了,再降一维:

\[S(i,r)=\sum_{l^\prime\le r} f_{i,l^\prime,r} \\ \Rightarrow L(i,r)=\sum_{r^\prime<x} S(i,r^\prime) \]

由此我们发现答案 \(F(n)\) 可以用 \(S\) 表示为 \(F(n)=\sum\limits_r S(i,r)\),这启发我们能不能不借助 \(f\) 而直接用 \(L\) 得到答案。推导一下 \(S_L\)

\[\begin{aligned} S(i,r) &= \sum_{l\le r} f_{i,l,r} \\ &= \sum_{l\le r}P(l,r)\times \left[F(i-1)-L(i-1,l)-L(i-1,m-r+1)\right] \\ &= \omega(m-r)\sum_{l\le r}\omega(l-1)\times \left[F(i-1)-L(i-1,l)-L(i-1,m-r+1)\right] \\ &= \omega(m-r)\left[\left(\sum_{l\le r}\omega(l-1)\right)[F(i-1)-L(i-1,m-r+1)]-\sum_{l\le r}\omega(l-1)\times L(i-1,l)\right] \\ \end{aligned} \]

直接就完成了!我们发现 \(F(i-1)\) 可以通过 \(S(i-1,x)\) 求和得到,并且维护 \(\omega(l-1)\)\(\omega(l-1)\times L(i-1,l)\) 的前缀和即可实现 \(O(1)\) 转移,总状态数为 \(O(n^2)\),时间复杂度 \(O(n^2)\)

*3100,恐怖如斯

第3场

T3 Brute

简要题意:给定无向连通图和 \(d\),求所有满足 \(\forall d_i\ne -1,dist(u,i)=d_i\) 的点 \(u\)\(n\le 5\times 10^4,m\le 10^5\)

显然对每个 \(i\) 其合法点集的交就是最终的答案,考虑怎么刻画 \(dist(u,i)=d_i\),如果我们直接对每个点 \(i\) 开始跑一遍 \(\mathrm{bfs}\) 就太唐了,只能做到 \(O(nm)\)。我们思考能不能将 多次单源 \(\mathrm{bfs}\) 变成一次多源,考虑这样一个建图:构建一个超级源点 \(S\),向所有 \(d_i\ne -1\) 的点 \(i\) 连一条边权为 \(-d_i\) 的边,然后从点 \(S\) 开始跑最短路。这样有什么作用?我们发现原来的 \(dist(u,i)=d_i\) 等价于此时的 \(dis_u=0\)。但是注意,我们还要求所有的 \(i\)\(u\) 都满足要求,即所有 \(i\)\(u\) 的最短路都应当是 \(0\),这在新图上就很好做了,直接在最短路树上跑可达性统计即可,即我们对每个点用 bitset 维护一个集合 \(S_u\) 表示哪些点 \(i\) 到点 \(u\) 是最短路。跑最短路时如果一条边 \((u,v)\)\(dis_v=dis_u+w\) 则说明在最短路上,我们让 \(S_v\leftarrow S_v\cup S_u\) 即可。

这样时间复杂度是 \(O(m\log n+\frac{nm}{\omega})\),可以通过。

图论(+根号分治?)

CF1056H Detect Robots

考虑刻画一下是Human的条件。如何对于两条从 \(A\to B\) 的路径判断其是否不同?朴素做法就是从前往后枚举每个字符看看其是否相同,仔细思考后我们发现可以将两条路径刻画成:

\[\begin{aligned} S_1: A\space C \space \dots B \\ S_2: A\space D \space \dots B \end{aligned} \]

然后是Human就等价于存在 \(C\ne D\)。因为枚举所有的 \(A,B\) 会使得我们对中间的每个字符都进行判断,以一种递归的形式完成了转化。接着考虑对这种形态的所有串对都完成判断。

观察到题目中保证了 \(\sum k=N\),我们尝试使用根号分治,取 \(B=\sqrt{N}\),对串长按照其长度 \(L\le B\)\(L>B\) 分为小串和大串。

考虑对小串间使用朴素的暴力,我们直接对每个小串暴力枚举子串 \([A\space C\space \dots B]\),并看看之前枚举的串中是否出现了 \(C\ne D\) 即可。分析一下时间复杂度,总共有 \(O(\frac{N}{B})\) 个小串,枚举需要 \(O(B^2)\),因此处理小串时间复杂度为 \(O(\frac{N}{B}\times B^2)=O(NB)=O(N\sqrt{N})\)

考虑大串对小串和大串,大串的个数不超过 \(\sqrt{N}\),如果我们可以设计出一个 \(O(N)\) 判断某个大串的方法即可解决。记大串为 \(S\),注意到我们可以将每个串都枚举一遍,并且每个字符在每个串中最多出现一次,记现在枚举到某个串 \(T\) 的字符 \(b_i\)\(A\),其后面跟着字符 \(C\),那么我们要形成 \(A\space C \space \dots B\) 的判断形式,需要在 \(S\) 中找到匹配 \(A\space D\space \dots B\),记 \(T[i+1,n]\) 中在 \(S\) 里出现最靠后的位置为 \(p\),我们令这个位置作为 \(B\),然后再在 \(S\) 中找 \(T_i\) 出现的位置作为 \(A\),再令 \(C=T_{i+1},D=S_{p+1}\) 即可形成判断匹配,那么我们倒着扫,维护 \(p\),判断 \(T_{i+1}\ne S_{p+1}\) 即可。这部分时间复杂度也是 \(O(N\sqrt{N})\)

因此总时间复杂度为 \(O(N\sqrt{N})\)

P7320 「PMOI-4」可怜的团主

很牛的构造!若无从下手,考虑一些图上的结构,如 \(\mathrm{dfs}\),跑出这个图的 \(\mathrm{dfs}\) 树后,考察有什么性质。

引理:对于一棵拥有 \(k\) 个叶子的树,可以通过 \(\lceil\frac{k}{2}\rceil\) 条路径完成覆盖。

由此我们对叶子数量 \(cnt\) 分类一下:

  • \(cnt\ge \lfloor\frac{n}{3}\rfloor\),这个简单,叶子间显然两两不相邻,可以直接拎出来 \(\lfloor\frac{n}{3}\rfloor\) 个构成独立集。

  • \(cnt<\lfloor\frac{n}{3}\rfloor\),根据上述引理,可以通过不多于 \(\lceil\frac{n}{6}\rceil\) 条路径完成覆盖,构造就是考虑将叶子按照 \(\mathrm{dfn}\) 排序后 \((i,i+\frac{cnt}{2})\) 配对,可以证明这样足以覆盖所有点。

注意根的度数为 \(1\) 时的特殊情况。

CF1508C Complete the MST

还有人类吗?对最小生成树乃至图论整体有了更深层次的理解。

异或和为 \(0\)?记原来的边权异或和为 \(x\),那么这意味着新边的异或和为 \(x\)。最小生成树权值最小?我们感性理解,这想要我们的边权中 \(0\) 尽量多,这样选 \(0\) 的边可以不需要花费。那我们大胆猜一手:

引理:最优解中添加的边只有一条边权为 \(x\) 的边,其他边的边权都是 \(0\)

试图证明它?考虑反证。假设最优解中选择了 \(k>1\) 条边权不为 \(0\) 的边,分别为 \((u_1,v_1,w_1),(u_2,v_2,w_2),\dots,(u_k,v_k,w_k)\),那么我们可以做一个等价变换将这些边变成 \((u_1,v_1,x),(u_2,v_2,0),\dots,(u_k,v_k,0)\),这样显然合法且对最小生成树无影响。否则我们可以让选择的那条边的边权设为 \(0\),这样同样合法且使得最小生成树变得更优。由此我们证明了最优解一定是只有一条边权为 \(x\) 的边,其他边的边权都是 \(0\)

接着考虑怎么求 \(\texttt{MST}\),先假设我们没有一条边选 \(x\) 这个限制,即所有待定边都是 \(0\),这时的最小生成树在 \(\texttt{Kruskal}\) 算法时会先处理所有待定边,并将这些点全部缩起来,由此我们发现这等价于在原图的补图上求连通块,然后在连通块间跑 \(\texttt{MST}\)。补图的连通块也是一个经典问题,其做法可以看大学习。求出后,我们就可以在补图上跑出 \(\texttt{MST}\),记这个的答案为 \(ans\)

接下来我们要强制选上一条边权为 \(x\) 的边。分讨一下:

  • 如果存在一个由待定边构成的
    这种情况下,我们可以将这个环造成 \(0-0-\dots-x-\),根据最小生成树的性质,这条边权为 \(x\) 的边将会没有作用,证明考虑 \(\texttt{Kruskal}\),一定会先加入边权为 \(0\) 的边,而加入边权为 \(x\) 的边时其两端已经连通,因此这条边被忽略了。此时答案就是 \(ans\)

  • 如果不存在...的环
    此时我们要尽量减少 \(x\)\(\texttt{MST}\) 造成的影响,考虑找一条边权尽量小的边 \(e\) 来替换掉 \(x\),我们发现这需要满足 \(e\) 与补图 \(\texttt{MST}\) 形成了一个环 \(C\),并且这个环 \(C\) 上存在至少一条待定边 \(y\),这样我们可以在 \(y\) 处填边权为 \(x\) 的边,这样 \(e\) 会偏序掉 \(x\),证明同上,于是 \(x\) 就被 \(e\) 替换掉,得到答案为 \(ans+e\)

于是就做完了。时间复杂度为 \(O(m\log m)\)

一些细节:如何判断是否存在待定边组成的环?注意到无环 \(\Leftrightarrow\) 是森林 \(\Leftrightarrow\) 边数 \(=\) 点数 \(-\) 连通块数,因此我们记边数 \(E=\frac{n(n-1)}{2}\),连通块数为 \(cnt\),无环等价于 \(E=n-cnt\)

CF1361E James and the Chase

看到可达性、强连通等字眼,同理考虑 \(\mathrm{dfs}\) 树。如何快速判断一个点 \(x\) 是不是好点?考虑以 \(x\) 为根建出 \(\mathrm{dfs}\) 树,树边不需要考虑,我们考虑其余的非树边:前向边、返祖边、横叉边。我们发现,如果不存在前向边和横叉边,则 \(x\) 是好点,因为如果存在这两种边,到某个点的简单路径条数一定会不止一条。

那么可以直接用栈来判断每个点出去的边是不是只有树边或是返祖边,如果出现了不合法的两种非树边则不合法。于是我们可以 \(O(n)\) 判断某个点是否是好点。但是直接枚举点判断显然是不行的,考虑利用性质,由于好点个数不足 \(\frac{1}{5}\) 就不合法,因此考虑随机化,随机选 \(100\) 个点并判断,如果这样都找不到一个合法点,那么可以近似认为不合法,因为这样判断错误的概率 \((\frac{4}{5})^{100}\to 0\)

那么假设我们现在找到了一个好点 \(x\),如何通过这个点找到其他的好点?还是分析性质,由于原图是强连通的,因此对于 \(\mathrm{dfs}\) 树上的每个点 \(u\),其子树中一定会有返祖边,否则其无法到达祖先链,同时我们发现,如果 \(u\) 想要成为好点,那么返祖边有且仅有 \(1\) 条,否则其可以通过不止 \(1\) 条路径到达 \(\mathrm{fa}_u\)

顺便记这条边到达的点为 \(w\),我们声称 \(u\) 是好点等价于 \(w\) 也是好点。这个可以通过【\(u\)\(\rightarrow\) \(w\) 好】和 【\(w\)\(\rightarrow\) \(u\) 好】来证明。

那么思路就很明了了,找到所有返祖边 \((w,v)\),运用树上差分在这条返祖边贡献的链上加贡献,遍历一遍即可找到所有好点。

时间复杂度 \(O(c\cdot n)\)

字符串

P3426 [POI 2005] SZA-Template

border题。直接令 \(f_i\) 表示恰好完成前 \(i\) 个字符的印刷所需要的最小印章长度。

注意到你可以直接用整个串做印章,即可以 \(f_i=i\)。对于不用整个串做印章的情况,观察一下盖印章的过程,我们注意第一次印和最后一次印,这两个都是同一个印章 \(T\),而正好构成了 \(S[1,i]\) 的前后缀,因此 此时 \(T\) 一定可以覆盖 \(S\)\(\mathrm{border}\),也即 \(f_i\) 另一个取值是取到 \(f_{nxt_i}\)。由此我们发现,\(f_i\) 只有 \(i\)\(f_{nxt_i}\) 两种取值。

由于要尽量小地覆盖,所以要尽量取到 \(f_{nxt_i}\),但是这是有条件的,对于 ___T___......___T___ 的情况,中间的部分不一定能够被 \(f_{nxt_i}\) 的印章盖好。考虑找到 \(f_{nxt_i}\) 能覆盖到的最远位置 \(p\),如果 \(f_{nxt_i}\ge i-p\) 则可以取到 \(f_{nxt_i}\),证明这样一定合法:

SZA-Template.png

其重叠部分可以通过 \(\texttt{border}\) 相互推得相等。因此成立。

于是可以开桶记录最大的 \(p\),做到 \(O(n)\)

P5840 [COCI 2014/2015 #5] Divljak

多模式串个数计数是很板的,直接对 \(S_i\) 建出 \(\texttt{ACAM}\),插入一个字符串 \(T\) 时,在 \(\texttt{ACAM}\) 上跳这个字符串,并将遍历到的每个点 \(u\)\(\texttt{fail}\) 链答案进行更新。但是直接链加对吗?审题注意到计算的不是出现次数的和,而是有几个,换言之,对同一个模式串 \(T\),有就只会计数一次,那么我们加 \(\texttt{fail}\) 链时需要改成覆盖,而非直接加。

如果是加可以用树上差分直接做,但是覆盖需要去重,对于公共链只算一次贡献。考虑这样一个算法:将需要加的点 \(u_1,u_2,\dots,u_k\) 按照 \(\mathrm{dfn}\) 序从小到大排序,先进行常规的树上差分,即每个点处 \(c_{u_i}\)\(1\),而对于相邻两个 \(u_i,u_{i+1}\),对他们的公共链去重,使 \(c_{\mathrm{lca}(u_i,u_{i+1})}\)\(1\),这样做是对的因为 \(\mathrm{dfn}\) 序是遍历树的顺序,这样能保证容斥的完整性。那么直接一个树状数组即可维护,时间复杂度 \(O(|S|\log |S|)\)

P6640 [BJOI2020] 封印

考虑令 \(len_i\) 表示以 \(i\) 结尾的最长的 \(T\) 的子串,即最大的 \(len_i\) 使 \([i-len_i+1,i]\)\(T\) 的子串,那么 \(\mathrm{LCP}(S,T)=\max\limits_{i=1}^n len_i\),如果放在区间里也同理,但是不能捅出左边界,因此是 \(\mathrm{LCP}(S[l,r],T)=\max\limits_{i=l}^r \set{\min(i-l+1,len_i)}\),我们发现如果能求出 \(len_i\) 那么简单分讨一下就做完了。

\(len_i\) 考虑建出 \(T\)\(\texttt{SAM}\),从前往后遍历 \(S\),并维护前缀在 \(\texttt{SAM}\) 上的匹配节点 \(p\),如果可以直接接上,即 \(\mathrm{ch}[p][S_i]\) 非空,那么有 \(len_i=len_{i-1}+1\),否则我们跳 \(\mathrm{father}\) 直到可以匹配上,此时 \(len_i=|\mathrm{endpos(p)}|+1\)。于是可以 \(O(n)\) 解决,最终时间复杂度是 \(O(n\log n)\)

P7409 SvT

SAM是唐唐,这次尝试SA。考虑对 \(S\) 跑SA,找出height数组 \(h_i\),我们熟知,令 \(rk_i<rk_j\)\(\mathrm{LCP}(\mathrm{suf}_i,\mathrm{suf}_j)=\min\limits_{k=rk_i+1}^{rk_j} h_k\)。那么先考虑用 \(rk\) 来表示给出的后缀,并将这些后缀按照 \(rk\) 排序,然后我们就要求:

\[\sum_{1\le i<j\le t} \min_{k=rk_i+1}^{rk_j} h_k \]

但是我们还是不能直接求解,因为 \(rk\) 的范围是 \([1,n]\),如果直接套单调栈或者分治等方法那么就与询问总个数有关,会爆炸,考虑挖掘一点性质。我们发现这个 \(\min\) 是可以拆的,具体的,我们令 \(w_i=\min\limits_{k=rk_{i-1}+1}^{rk_i} h_k\),那么 \(\min\limits_{k=rk_i+1}^{rk_j}=\min\limits_{k^\prime=i+1}^j w_{k^\prime}\)\(w_i\) 可以通过对 \(h\) 建ST表查,而剩下的对 \(t\) 个求 \(\sum\min\) 状物的问题就很简单了,直接用单调栈拆掉贡献即可。令 \(s=\sum t\),时间复杂度 \(O(s\log s)\)

P6095 [JSOI2015] 串分割

后缀数组妙用。

首先注意到数字串中没有 \(0\),那么大小的第一关键字就是长度,于是这个最优串的长度一定是 \(\ell=\left\lceil\dfrac{n}{K}\right\rceil\),而其他的串要么是 \(\ell\) 要么是 \(\ell-1\)

看到环,先断环成链复制一份在后面,记这个串为 \(S\)。由于最大串定长,因此这个串一定是 \(T=S[i,i+\ell-1]\) 的形式,考虑怎么求这个串在哪里,注意到这个问题是具有单调性的,即如果串 \(S[i,i+\ell-1]\) 作为最大串可以那么 \(S[j,j+\ell-1]\ge S[i,i+\ell-1]\) 作为最大串也可以,但是直接二分串是不现实的,考虑对 \(S\) 跑后缀排序,求出每个后缀的排名 \(rk_i\),那么由于定长,\(S[j,j+\ell-1]\ge S[i,i+\ell-1]\Leftrightarrow rk_j\ge rk_i\)(其实这个是不严谨的,但是对我们求答案无影响)。于是我们可以转而二分这个 \(rk=mid\)

考虑如何判断 \(rk_i=mid\) 是否可行,我们相当于要找到一种由 \(K\) 个串拼成的分割方案,这个方案的串长 \(\ge n\)。考虑分割方案中分出的一个以 \(x\) 为左端点的串,其长度为 \(\ell\)\(\ell-1\)。若 \(rk_x\le rk_i=mid\) 那么说明这个串无论选那个长度都不会大于 \(T\),根据贪心我们肯定尽可能让这个串长,即让这个串长度取到 \(\ell\),若 \(rk_x>rk_i\) 那么这个串如果选长度为 \(\ell\) 就爆掉了,所以此时其串长为 \(\ell-1\)

那么我们只需要枚举这个分割方案的左端点,然后往右边不断拼上 \(K\) 个串,最后判断是否拼到长度 \(\ge n\) 即可。但是这样枚举的分割点有 \(O(n)\) 个,因此判断复杂度变成了 \(O(nK)\),无法接受。考虑优化,我们找一下性质,我们声称只需要枚举左端点 \(\le \ell\) 即可。考虑现在 \(n=10,\ell=4\),有一种分割方案 \(\texttt{(abcd)(efg)(hij)abcdefghij}\),如果我们以 \(1\) 为左端点会找到这种分割方案,而如果以 \(\ell+1=5\) 为左端点也会找到一种等价方案 \(\texttt{abcd(efg)(hij)(abcd)efghij}\),只不过调换了一下顺序。同理我们发现,以 \(i+\ell\) 为左端点开始分割的方案跟 \(i\) 的方案其实都是循环同构的,因此我们只需要枚举 \(i\le \ell\) 即可。这样判断的时间复杂度是 \(O(\ell K)=O(n)\),总时间复杂度为 \(O(n\log n)\)

博弈论

P3480 [POI 2009] KAM-Pebbles

阶梯 Nim

规则:\(n\) 阶的阶梯上有 \(a_1,a_2,\dots,a_n\) 个石子,每个人可以选择将任意多石子从 \(i\) 拿起,放到 \(i-1\) 阶,或者拿走 \(1\) 阶的任意多石子,不能操作者输。

结论: 这与只看奇数台阶的普通Nim本质相同。证明:

  • 若对方把奇数堆石子放到偶数堆:这相当于普通Nim的拿任意多石子操作
  • 若对方把偶数堆石子放到奇数堆:可以将这些石子再向下传,对奇数堆的局面没有任何影响。

因此结论正确,只需要取出奇数位求异或和判断即可。

解法

要求 \(a_i\ge a_{i-1}\) 不好看,用差分转化成 \(c_i=a_i-a_{i-1}\ge 0\),那么从 \(a_i\) 拿石子相当于令 \(c_i\)\(x\),令 \(c_{i+1}\)\(x\),可以刻画成一个从 \(i\)\(i+1\) 放石子的阶梯Nim,这次反过来做即可,即这个游戏等价于位置奇偶性为 \((n\bmod 2)\) 的普通Nim。

P2575 高手过招

有简单的 \(O(2^mm)\) 直接 \(\mathrm{SG}\) 暴力做的做法。考虑 \(m=100\) 怎么做。

这个找到空位放石子的操作有点难处理,我们手玩一下局面:

初始局面:■□■■■□■□

操作黑 \(3\):■□□■■■■□

我们关注每个白棋前面黑棋形成的连通块大小,初始是 \(\set{1,3,1}\),操作后是 \(\set{1,0,4}\),再次发现,这就等价于一个阶梯Nim的过程,将棋子从 \(i\) 移动到 \(i+1\)。那么与上题类似可以求异或和随便做。然后用 \(\mathrm{SG}\) 缝起来即可。

P2490 [SDOI2011] 黑白棋

k-Nim

规则: 在普通Nim的基础上,每个人每次可以选择不超过 \(k\) 堆石子取。

结论: 将每堆石子的个数表示为二进制数,用 \(r_i\) 表示第 \(i\) 位的和 \(\pmod {(k+1)}\) 的结果,结论是,如果 \(\exists i,r_i\ne 0\),则先手必胜,否则先手必败。证明:

  • 若当前所有 \(r_i=0\),那么拿 \(k\) 堆石子使得某一位的和变化绝对值不超过 \(k\),因此某一位的 \(r_i\) 必定变得非 \(0\),故会变成存在 \(r_i\ne 0\) 的局面。

  • 若存在 \(r_i\ne 0\),对于每个 \(r_i\ne 0\),找到这一位上为 \(1\)\(r_i\) 个数,取 \(x\oplus 2^i\) 个石子即可使这一位变成 \(0\),可以证明这样操作一定是合法的。

最后的必败态就是 \(\forall i,r_i=0\),因此结论成立。

解法

记任意两个白黑棋子之间的距离为 \(a_i\),则就是一个每次最多取 \(d\) 个的 k-Nim,那么只需要对 \(a_i\) 计数即可。注意到 \(\sum a_i=n-k\),我们反过来统计每一位 \(1\) 的个数 \(cnt\bmod {(D+1)}=0\) 的个数,然后容斥掉即可,直接对这个按位 \(\mathrm{dp}\) 随便做。

P8347 「Wdoi-6」另一侧的月

毫无头猪则考虑特殊形态,考察最后一个操作者操作后会怎么输掉,这当且仅当所有连通块都只有一个点,即所有剩余点的 \(deg_u=1\)。那我们猜一手,我们认为如果刚开始局面所有点的 \(deg\) 都是奇数则先手必败,否则先手必胜。考虑证明这个猜想。

令所有点 \(deg\) 都为奇数的局面为状态 \(A\),那么我们相当于要证明:

  • \(A\) \(\to\)\(A\),这个是简单的,随便操作一个点即可造出一个度数为偶数的点,选择其所在连通块即可。
  • \(A\) \(\to\) \(A\),如果有点为偶数,考虑怎么再找到一个全是奇数的连通块。我们找到一个子树,使得其子树根 \(u\) 为偶点,子树内部为奇点,这显然是可以的,然后我们操作 \(fa_u\) 并保留 \(u\) 所在子树即可。

由此结论正确。

[AGC010D] Decrementing

我们注意到,如果出现了 \(a_i=1\),那么剩余的奇偶性可以直接通过 \([\sum (a_i-1)]\bmod 2\) 判断,也就是到达 \(1\) 时结果就确定了,因此胜负的关键因素在于 \(\sum(a_i-1)\) 的奇偶性,换言之,在于偶数个数的奇偶性。因此博弈双方一定会尽力去使得奇偶性变得有利。

我们思考何时奇偶性才可能发生变化,可以发现,只有除 \(\gcd\),并且 \(2|\gcd\) 时才可以改变奇偶性,从这个出发我们进行分讨,记 \(a_i\) 中的奇数个数为 \(cnt(cnt\ge 1)\)

  • \(cnt\ge 2\)。我们声称此时输赢只与此时的偶数个数有关。我们从博弈双方的角度来思考这个问题,如果当前偶数个数的奇偶性对一方有利,那么对另一方是不利的,我们发现博弈双方都有操作方法来克制对方,使得对方没办法达到对自己优的局面,因此此时的输赢就已经固定。

  • \(cnt=1\)。那么此时如果操作后奇偶性对先手不利那么先手就只能操作这个奇数,操作后递归下去做即可。否则如果有利先手会使其转到 \(cnt\ge 2\) 并由此必胜。

我们发现最多递归 \(O(\log V)\) 层,时间复杂度 \(O(n\log^2V)\)

第4场

P14015 [ICPC 2024 Nanjing R] 生日礼物

Ad-hoc,对人类无解。考虑一个特别牛的转化,我们将原串的所有偶数位 \(01\) 反转,这样原本消掉 \(00,11\) 的操作就被我们转化成了消去 \(01,10\) 的操作!并且这两个问题显然是等价的,而消掉 \(01,10\) 就再简单不过了,最后一定消成全 \(0\) 或全 \(1\) 的形态,不妨记转化后的 \(0,1,2\) 个数分别为 \(c_0,c_1,c_2\),那么没有 \(2\) 的情况下答案就是 \(C=|c_0-c_1|\),如果有 \(2\),那么我们先不管这些 \(2\),在 \(01,10\) 相消的过程中如果遇到 \(2\) 挡住则再将这个 \(2\) 确定下来并贡献一次消去,因此如果 \(2\) 不够抵消掉所有数,即 \(cnt_2<C\) 时答案就是 \(C-cnt_2\),否则会多出来 \(cnt_2-C\)\(2\),那么直接对半分即可,答案就是 \((cnt_2-C)\bmod 2\)

CF2064E Mycraft Sand Sort

直接以原图为例进行观察:

注意到:每一列在重力排序后最终落下的颜色排列要是相同的,因此 \(p^\prime\) 只能由 \(p\) 交换同色行得到,否则从列上看顺序就会乱。

考虑两个同色行 \(i,j\) 在什么情况下才可以交换。我们注意到,这当且仅当:\(\forall k\in (i,j)\wedge c_k\ne c_i,p_k<min(p_i,p_j)\),这是因为如果中间没有凸出来的那么换不换其实没有本质影响,而如果突出来一个则肯定会有一列的相对顺序出现问题,因此这就是可以换的充要条件。因此可以交换的就是没有被 \(k\) 分开的一个个极大同色连通块。

维护这个其实比较简单,从小到大枚举 \(p_x=i\),用并查集和链表即可简单维护极大同色连通块。时间复杂度 \(O(n\alpha)\)

P11024 [COTS 2020] 定序 Redoslijed

过于牛了。考虑暴力怎么做,这种区间覆盖问题套路地考虑时光倒流,将操作序列倒过来考虑,那么某个位置 \(i\) 的最终颜色就是第一次覆盖到这个点的操作颜色。

于是就有一个很显然的暴力,我们考虑现在没有被用到的操作有哪些是可以作为当前的最后一次操作的,不难发现这等价于 \(\forall x\in [l_i,r_i]\)\(x\) 位置要么在之前的操作已经被染好色,我们称这种位置被标记,要么这个位置的目标颜色 \(b_x=c_i\),如果这个区间中每个位置都满足条件,那么当前的操作 \(i\) 可以被使用。那么我们可以开一个队列,存目前可以用的操作,取出操作 \(i\) 后将 \([l_i,r_i]\) 标记,然后暴力找找有哪些操作又可以作为新的最后操作,将其加入队列。这样暴力应可以做到 \(O(mn)\)

考虑怎么优化,有一个很牛的trick(或者说等价于线段树优化建图?),考虑将每个 \([l_i,r_i]\) 放在线段树上,在线段树上会被自然的分割成 \(O(\log n)\) 个子区间。我们原来的条件相当于这些子区间都满足条件,那么考虑对每个操作维护一个计数器 \(cnt_i\) 表示分割成的子区间中有多少个还没有满足条件,如果 \(cnt_i=0\) 说明全部子区间都满足,这个操作就可以被加入队列中。

考虑怎么判断子区间的合法性,我们对线段树上的每个节点维护 \(val_u\),若 \(val_u=-2\) 表示这个节点表示的子区间已经满足全部位置都被标记,此时这个子区间可以直接合法,若 \(val_u=c(c\ne -1)\) 则表示这个子区间没有被标记的位置都是同一种颜色 \(c\),此时若操作的颜色 \(c_i=c\) 则这个子区间相对于这个操作而言就是合法的,而如果 \(val_u=-1\) 表示这个区间没有被标记的位置有至少 \(2\) 种颜色,此时这个子区间一定非法,有了这个 \(val\),我们可以更新以这个节点为子区间的操作的 \(cnt\)\(val\) 可以在 pushup 时简单维护,并且由于 \(val\) 最多只会 \(-1\to c\to -2\),因此每个 \(val\) 最多作用 \(2\) 次,复杂度也是对的。而对于修改,我们考虑直接暴力修改,如果 \(val_u=-2\) 则跳过这个区间,这样是对的因为每覆盖一次会解锁其子树内的所有结点,势能分析一下,时间复杂度是 \(O(n\log n)\)

posted @ 2026-01-24 09:13  STDJCY  阅读(13)  评论(0)    收藏  举报