NOIP 复习互讲做题笔记
2025.9.28 yt Counting
大概率会搬过来。
2025.9.29 czx Matrix
2025.10.9 xjy Number Theory
2025.10.9 zxk Search
P1979 [NOIP 2013 提高组] 华容道
思考过程:(移动空格的 trick)空格先移到关键棋子旁,之后每一步棋子欲往,则空格先至,而棋子后至,且空格始终与棋子四连通。注意特判起点即终点的情况,此时不必移动空格。
建新图:以 \((x,y,0/1/2/3)\) 表示棋子在 \((x,y)\),空格在其哪一侧,它作为 状态(点);转移(边) 即棋子向某个方向移动一步,边权为空格移动、棋子走一步的路程。于是枚举初末状态,空格移到棋子旁可以在询问时 BFS,从初始态到终末态可以在询问时跑 Dijkstra,唯一的问题是如何建图。枚举每个状态,BFS 求转移边权值(空格路程 \(+1\))即可。
2025.10.10 xwb Graph Theory
P6822 [PA 2012 Finals] Tax
点权,和两侧的边有关,不妨点边互化,之后跑 Dijkstra,枚举出发边(原来的边)和结束边(原来的边)计算贡献即可,注意特判 \(n=1\)(起点等于终点),此时不用走。
现在要对每个点连着的一堆边两两建边,边权为原边权的 \(\max\),考虑优化建图(对每个这样的结构):
从小到大排序,对每个点 \(u\) 建一个虚点 \(u'\)。连 \((u\to u',val_u),(u'\to u,0)\),之后用这一排 \(u'\) 做前后缀优化建图,处理边权的变化量,连 \((u'\to(u+1)',val_{u+1}-val_u),((u+1)'\to u',0)\) 即可。
这样实点之间的边权正确,且没有多余的路径,故把多个这样的结构合在一起也合法。
P11564 【MX-X7-T5】[LSOT-3] 你的列车是生存战略
最短路边权是 \(\min\),这个是 \(\min\) 套 \(\min\),可以拆成两条边。
不妨考虑把代价放在“中继点”上,\(c_i|c_j\) 与 \(d_i\&d_j\) 本质相同,这里只考虑前者。对 \([0,2^k-1]\) 中每个 \(x\) 建虚入点和虚出点,其间连边权为 \(a_x\) 的有向边;每个点连向 \(c_i\) 的超集的入点,再由 \(c_i\) 的超集的出点连向自己,边权都是 \(0\)。由于 \(a\) 单调不降,\(b\) 单调不升,我们有 \(>c_i|c_j\)、\(<d_i\&d_j\) 错解不优。
优化超集 / 子集连边,枚举把哪一位变成 \(1\) / 变成 \(0\) 即可。另一种理解是建出子集和 / 超集和 DP 的自动机(DAG),省略掉一维可能相当于合并仅该维度不同的所有点。
P9140 [THUPC 2023 初赛] 背包
同余最短路处理大空间最优化完全背包的板子,使用转圈法。
注意“恰好”的初值,以及 vis 的更新。
CF1120D Power Tree
按 DFS 序排列叶子,则每棵子树对应区间加,要求对于任意整数序列,都可使所有数变为 \(0\)。
差分,变为 \(a_{l}\leftarrow a_{l}+x,a_{r+1}\leftarrow a_{r+1}-x\),要求 \(a_1,\ldots,a_{cnt}\) 都 \(=0\),而 \(a_{cnt+1}\) 任意。从左到右处理每个 \(a_i\),若有 \(l=i\) 的操作,就可以令 \(a_i=0\),把值往后面传,否则不合法。
于是发现:一个合法的区间集合,与 \((l,r+1)\) 边形成的点集为 \(\{1,2,\ldots,cnt+1\}\) 的生成树形成双射。求最小生成树即可。
P8207 [THUPC 2022 初赛] 最小公倍树
稠密图 MST 好题。
\(\operatorname{lcm}(a,b)={ab\over\gcd(a,b)}\),考虑枚举 \(\gcd=x\)。现在抓出 \(S=\{y\mid y\in[L,R],x\mid y\}\),考察 \(S\) 的完全图的 MST。
我们记 \(S\) 中的元素为 \(ax,bx\),但 \(\gcd(ax,bx)\geq x\),不一定 \(=x\)。不妨加入不优的错边 \((ax\leftrightarrow bx,abx)\),这样完全图中所有边(无论对错)边权都是 \(abx\),且每条边仍会被正确的 \(\gcd\) 考虑到。
容易发现,每个 \(S\) 的完全图是新边集的一种划分。对于每个完全图,其一种 MST 是每个点都连向 \(\min S\),且可以用 Kruskal 得到(除了 \(\min S\) 的每个点,相邻的最小边就是这条边)。那么把这些边抓出来,在全局求 MST 即可。
2025.10.13 lr Greedy & Game
P2490 [SDOI2011] 黑白棋
将一对“白——黑”棋子视作一堆石子,石子数为中间的空位数。那么游戏等价于 Nim - \(d\)。正难则反,总方案数为 \({n\choose k}\),统计先手必败。
我们先确定每一堆的大小,再插入剩余的空格。对于前者进行 DP:设 \(f_{i,j}\) 表示考虑了二进制位 \([0,i]\),当前填了 \(j\) 个石子的方案数。
最后如何插入空格?枚举填了 \(j\) 个石子,则还剩 \(n-k-j\) 个空格,要把它们插在 \(k/2\) 段之间或左右,即要把它们分为 \(k/2+1\) 个可空段,插板法即可。
P3480 [POI 2009] KAM-Pebbles
令 \(d_i=a_i-a_{i-1}\ (1\leq i\leq n,a_0=0)\),则取石子的限制相当于 \(\forall 1\leq i\leq n,d_i\geq0\)。
\(a_i\leftarrow a_i-x\ (i\in[1,n])\),造成 \(d_i\leftarrow d_i-x,d_{i+1}\leftarrow d_{i+1}+x\),相当于一个向右的阶梯 Nim,石子堆是 \(d_1,\ldots,d_n\)。
P5363 [SDOI2019] 移动金币
将每个金币和上一个金币之后(或到左边界)的部分看做一个石子堆,则原游戏变为向右的阶梯 Nim。
类似 P2490 黑白棋 进行 DP,为了优化转移,可以预处理 \(g_k\) 表示选 \(k\) 个堆,其中有偶数个奇堆的方案数(直接用组合数写出和式)。
另一种做法是先只填奇堆,最后再对偶堆和最后一段插板。
P4279 [SHOI2008] 小约翰的游戏
Anti-Nim 板子。
2025.10.13 why Sqrt
P5309 [Ynoi2011] 初始化
由于没有 \(0\) 这个位置,修改相当于对所有 \(i\equiv y\pmod x\) 的 \(a_i\) 加 \(z\)。
根号分治:
- 对于 \(x>B\) 的枚举 \(i\),单点加、区间求和,用 \(O(1)-O(\sqrt n)\) 的分块平衡。
- 对于 \(x\leq B\) 的修改,考虑查询时枚举 \(x\),则这形如在值域上以 \(x\) 为块长分块,\([l,r]\) 对应的 \(y\) 是一个散块区间(\(l,r\) 在同一块),或若干整块(所有 \(y\))加两个散块(左边的后缀和右边的前缀),整块贡献都相同。那么对每个 \(x\) 维护以 \(y\) 为下标的前缀和即可,也可以再维护一个后缀和。
P4117 [Ynoi2018] 五彩斑斓的世界
第二分块。时隔一年,终于战胜!
每个位置独立,分块,逐块处理。要支持单点、整块修改,以及单点、整块查询。
称“值”为“颜色”,那么用并查集维护块内点的颜色,支持 \(4\) 种操作:将整个块的颜色 \(x\) 全部改为颜色 \(y\);改变单点的颜色;查询某颜色的个数;查询单点的颜色。做法同“斗恶龙”的分块做法,仍是整体变色时给消失的颜色建新的“代表点”。
整块修改:将 \(>x\) 的颜色向前平移,并上去。可能有很多颜色移动了还 \(>x\),此时并的操作没有使它们消失。这种情况大概是向左移动的后缀比较长,而不动的前缀比较短。于是考虑相对运动,将不动的前缀向右平移,而不移动那段后缀;这相当于启发式合并,并了就消失,与长剖优化 DP 原理相同。
详细分析,记当前的值域区间为 \([l,r]\),我们有两种策略:
- \([l,l+x]\to[l+x,l+2x]\)
- \([l+x+1,r]\to[l+1,r-x]\)
先尽量用 \(1\),要求 \(l+2x\leq r\),那么只有 \(l\to l+x\) 这一个点不会并进 \([l+x+1,r]\)。当 \(l+2x>r\) 时有 \(r-x<l+x\),那么 \([l+1,r-x]\subseteq[l,l+x]\),用 \(2\) 即可。每次操作后值域至少减小枚举的点数 \(-1\),那么枚举的势能只有 \((C+1)+m\)(颜色的值域是 \([0,C]\)),并查集中新建的点数也最多这么多。
\(1\) 结束后 \(l\leftarrow l+x\),\(r\) 不变;\(2\) 结束后 \(r\leftarrow l+x\),\(l\) 不变。现在我们会写整块修改了:
void Bmdf(int x) {
if(lval + x + 1 > rval) return ;
if(lval + 2 * x <= rval) {
for(int i = lval + x; i >= lval; -- i) trs(i, i + x);
lval = lval + x;
} else {
for(int i = lval + x + 1; i <= rval; ++ i) trs(i, i - x);
rval = lval + x;
}
}
显然 \(l\) 即整体向右平移的距离,可以少记一个变量。
单点修改后的颜色仍在原 \([l,r]\) 内,不会破坏势能。于是用并查集求颜色后判断是否修改,是则在并查集上改即可。单点查询直接在用并查集查颜色,整块查询查颜色的代表点的“siz”(类似并查集子树大小,但只有“位置”点算贡献)。
时间复杂度单根号带个 \(\alpha\),调块长后感觉不卡常;空间复杂度线性。
易错点:
-
void mdf(int x, int y) { // a[x] <- y int fx = fd(x); -- siz[fx]; fa[x] = rep[y]; ++ siz[rep[y]]; // fx, not rep[fx] } -
(整块查询的 corner case,防止数组越界等。)if(l == lp && r == rp) { if(x + lval <= rval) ans[j] += Siz(x + lval); } // x + lval <= rval
CF710D Two Arithmetic Progressions
数论做法:
依次令 \(L\leftarrow \max(L,b_1,b_2),b_1\leftarrow b_1\bmod a_1,b_2\leftarrow b_2\bmod a_2\),则对 \(x\) 的限制形如:\(x\in[L,R],x\equiv b_1\pmod{a_1},x\equiv b_2\pmod{a_2}\)。
xjy 说是 exCRT 板子。将两式写成一元一次方程,相减得到二元一次不定方程,用 exgcd 求通解后解不等式即可。要开 __int128。
根号分治做法:
第一步转化同上。
\(\max(a_1,a_2)>B\) 则可以枚举 \(x\),时间复杂度为 \(O({V\over\max(a_1,a_2)})\),否则考虑循环节:
\(x\bmod a_1,x\bmod a_2\) 的循环节分别为 \(a_1,a_2\),那么总的循环节为 \(\operatorname{lcm}(a_1,a_2)\),且每个大循环节内恰有一个合法的 \(x\)。于是找到 \([L,R]\) 中第一个合法的 \(x\)(可能没有),把它视作每轮循环的开头,用循环节长度求一共有多少个合法的 \(x\) 即可。时间复杂度为 \(O(\operatorname{lcm}(a_1,a_2))\)。
2025.10.16 jsh & wyc DP
CF2121H Ice Baby
LIS 的两种 DP 状态:\(f_i\) 表示以位置 \(i\) 结尾的 LIS 长度、\(f_i\) 表示处理完当前前缀时,长为 \(i\) 的 LIS 的最小结尾。二者类似交换定义域、值域,后者取值有单调性。
这里每个位置有多种取值,采用后一种状态。分讨一下每个状态转移到哪里,发现要实现单点插入、单点删除。由于单调性,用 multiset 维护即可。
P4484 [BJWC2018] 最长上升子序列
考虑从小到大插入每个数,DP 套 DP,叠合阶段。设 \(f_{i,S}\) 表示 \([1,i]\) 的排列,内层 DP 的状态为 \(S\) 的方案数。
由于插入的影响和位置强相关,我们用 LIS 的第一种状态:\(g_j\) 表示以位置 \(j\) 结尾的 LIS 的长度(\(g_0=0\))。注意到 \(g_{j-1}\leq g_j\leq g_{j-1}+1\),故 \(S\) 可以记录 \(g\) 的差分数组的 \([1,i]\) 位,状压至二进制。转移时枚举插入位置,对 \(S\) 的影响可以直接用位运算处理。
直接转移,每个 \(i\) 的时间复杂度是 \(O(2^ii)\),于是总时间复杂度为 \(O(2^nn)\)。过不了,但输入只有 \(n\) 且范围较小,打表即可。
一个很搞笑的事:打标的程序在本地空间开不下。首先 \(f_{i,S}\) 的 \(i\) 这一维可以滚成 \(0/1\),其次除了 \(i=0\) 时,\(g_1-g_0=1\),所以可以不在 DP 状态里记录 \(S\) 的最低位。这样就开下了。
当然也有可能能用 max 那个 CRT 卡空间的 trick。
P1858 多人背包
DP 状态添一维表示第 \(i\) 优解,或者认为原状态的值是前 \(\min(cnt,k)\) 优解。转移时归并即可,时间复杂度 \(O(nmk)\)。
P4170 [CQOI2007] 涂色
感觉 \(O(n^3)\) 做法真有点难,为啥只有蓝啊。
注意题目要求所有位置都被覆盖。
涂色区间相交但不包含可以拆成不交,故只考虑不交或包含的情况,由此想到区间 DP。进一步发现包含关系中,大区间的操作一定比小区间先执行。
覆盖操作可以倒序考虑,那么每个位置的颜色是其“首次(倒序)”涂色的颜色。
设 \(f_{l,r}\) 表示涂完 \([l,r]\) 的最小代价,直接的做法是枚举(正序)首次涂色的开头位置,在区间内做另一个 DP 拼接之后涂掉的区间,时间复杂度为 \(O(n^4)\)。但这题有更巧妙的做法。
若 \(s_l=s_r\),可以把 \(f_{l+1,r}\) 的操作序列中任意一次对 \(r\) 的操作 \([t,r]\) 扩展为 \([l,r]\),问题是如何保持 \([l+1,r]\) 不变。由于操作不交或包含,原操作序列中其他操作一定 \(\subseteq[l+1,t]\) 或 \(\subseteq[t,r]\) 或 \(\supsetneq[t,r]\)。对于 \(\supsetneq[t,r]\) 的操作,由于 \(r\) 是最右侧,可以去掉它的 \([t,r]\) 部分,转化为 \(\subseteq[l+1,t]\) 的操作。于是现在 \([t,r]\) 之外的所有操作要么和 \([t,r]\) 无交,要么被 \([t,r]\) 包含。被包含的本来就在 \([t,r]\) 之后,而无交的和 \([t,r]\) 的相对顺序不重要,故可以把 \([t,r]\) 变成的新操作挪到其他所有操作之前,使操作数不变,且 \([l+1,r]\) 保持原样。于是 \(f_{l,r}\leq f_{l+1,r}\),又由于 \(f_{l,r}\geq f_{l+1,r}\),得到 \(f_{l,r}=f_{l+1,r}\)。
若 \(s_l\neq s_r\),则存在一个最优解,使得不存在覆盖整个区间 \([l,r]\) 的操作。此时一定存在操作 \([l,k] \ (l\leq k<r)\),找到其中最大的 \(k\),那么所有操作分为 \(\subseteq[l,k]\) 的和 \(\subseteq[k+1,r]\) 的,分别是两个子问题。于是 \(f_{l,r}=\min_{l\leq k<r}f_{l,k}+f_{k+1,r}\),注意这里枚举的 \(k\) 可能不合上述定义,但一定会枚举到上述的 \(k\),而其他情况的组合意义也没错;最优化是允许方案重复的,所以正确。
时间复杂度为 \(O(n^3)\)。
P2466 [SDOI2008] Sue 的小球
先将包括出发点的所有点按 \(x\) 坐标排序,注意到任意时刻获得的彩蛋是包含出发点的一段区间,且每次从区间端点走到新的端点(给过程分段)。故可以设 \(f_{l,r,0/1}\) 表示当前获得了 \([l,r]\) 中的彩蛋,船在 \(l/r\),但不记录时间难以计算贡献。
由于每个彩蛋都要取,我们提前计算贡献,即每移动一段减去还未获得的彩蛋向下移动的距离,只需求出 \(v\) 的前缀和即可快速计算。DP 状态就表示这个代价的最小值,最后加上所有 \(y\) 坐标即可。
转移时枚举 \(l\leftarrow l-1\) 还是 \(r\leftarrow r+1\),时间复杂度为 \(O(n^2)\)。
P2135 方块消除
听说有个很厉害的“贡献提前计算”做法,但我还没学。
这种相邻合并的可以考虑区间 DP。
将题目输入给出的每个颜色段视作一个点。首先由于错解不优,可以消除任意一段颜色相同的点,而不一定要消除极长段。
接着设 \(f_{l,r}\) 表示删空区间 \([l,r]\) 的最大得分,转移时枚举最后一次消除的开头点 \(k\)。那么设 \(g_{l,r,x}\) 表示在区间 \([l,r]\) 中,保留 \(l\),可能还会保留一些与 \(l\) 颜色相同的点,保留的点长度之和为 \(x\),删除其他点(区间)的最大得分。
外层 \(n\to1\) 枚举 \(l\),内层 \(l\to n\) 枚举 \(r\),即可让 \(g,f\) 一起转移。时间复杂度为 \(O(m^3\sum a)\),\(\sum a\) 是总长。
AT_agc071_a [AGC071A] XOR Cross Over
每次把区间分成两段:区间 DP。
假设已确定分治树,考虑最终的单点值。自上而下处理,对于一个尚未切割的区间,其中所有点都要异或同一个数 \(S\)。切割时,另一侧异或上这一侧所有数原来的值,且(对异或分析奇偶性)若这一侧长度为奇数,则另一侧的 \(S\) 被抵消为 \(0\);否则另一侧 \(S\) 不变。那么每个叶子的最终值如下:向上走,直到第一次遇到长度为奇数的兄弟,最终值就是此时父亲区间的原权值异或和;如果找不到,则为根的区间的原权值异或和。
区间 DP 的过程中,我们在“区间异或和”那个结点处处理叶子的权值,那么要知道有多少叶子的权值是它。直接多开一维记录未被“截断”的叶子数不太现实,继续分析区间划分的奇偶性。奇区间必定拆为一奇一偶,那么最终会且仅会剩一个点未在内部算贡献;偶区间必定拆为两偶或两奇,最终每个点都会在内部算贡献。于是设 \(f_{l,r}\) 表示 \([l,r]\) 区间的最小贡献,但若 \(r-l+1\) 是奇数则不统计那个未被“截断”的点。转移时分讨拆成的两段的奇偶性:
- 两奇:\(f_{l,r}\leftarrow f_{l,k}+f_{k+1,r}+2\bigoplus_{i=l}^ra_i\)。
- 一奇一偶:\(f_{l,r}\leftarrow f_{l,k}+f_{k+1,r}\)
- 两偶:\(f_{l,r}\leftarrow f_{l,k}+f_{k+1,r}\)
答案为 \(f_{1,n}+[2\nmid n]\bigoplus_{i=1}^na_i\),初值为 \(\forall 1\leq i\leq n,f_{i,i}=0\)。
P3959 [NOIP 2017 提高组] 宝藏
贡献和深度强相关,数据范围极小,考虑按层状压 DP。
设 \(f_{i,S}\) 表示恰用点集 \(S\) 建了 \(i\) 层的最小代价,转移时枚举下一层的点集,则深度的代价系数不必在预处理时考虑;即使没有接到第 \(i\) 层的点上也有错解不优,无需理会。
为了辅助转移,设 \(g_{S,T}\) 表示将 \(T\) 中每个点接到点集 \(S\) 上的最小边权和,\(h_{u,S}\) 表示点 \(u\) 接到 \(S\) 上的最小边权,\(e_{u,v}\) 表示点 \(u,v\) 间的最小边权。按 \(e,h,g\) 的顺序处理三者,都容易直接 / DP 求出。
\(S,T\) 不交,等价于 \(T\) 是 \(S\) 的补集的子集。故时间复杂度为 \(O(m+n^22^n+n3^n)\),空间复杂度为 \(O(2^{2n})\)。
P2150 [NOI2015] 寿司晚宴
我们只关心每个数包含哪些质数,不妨求出 \([2,n]\) 中每个数的质因数集合。思考 \(n\leq30\) 怎么做,可以状压质数集合。对于最大的数据范围尝试根号分治:
- \(\leq\lfloor{\sqrt n}\rfloor\) 的质数只有 \(\{2,3,5,7,11,13,17,19\}\) 这 \(8\) 个,可以状压。
- \(>\lfloor{\sqrt n}\rfloor\) 的质数在每个数中不出现或只有一个,可以按此分类。
“无大质数”也算一类,一类类 DP。每个数有三种情况:不被选、被小 G 选、被小 W 选。限制:一个数的小质因数集合若与一人已占据的有交,则另一人不能选它;同一类的数,不能两个人都选。
设 \(f_{i,S,T}\) 表示处理了前 \(i\) 类的数,小 G、小 W 占据的小质数集合分别为 \(S,T\) 的方案数。
可以先处理“无大质数”这一类,设 \(g_{i,S,T}\) 表示处理了前 \(i\) 个数,两人占据的集合分别为 \(S,T\) 的方案数,枚举每个数转移即可。
之后一类类处理时把 \(f\) 作为初值丢进去 DP 再取出来:设 \(g_{i,S,T}\) 表示处理了前面所有类和当前类的前 \(i\) 个数,当前类不准小 W 选,\(S,T\) 与值的意义与 \(f\) 相同;对称地设 \(h_{i,S,T}\) 表示当前类不准小 G 选。转移给 \(f\) 时将 \(g,h\) 两种情况相加,那么当前类两人都不选的情况被算重了一次,要减去 \(f_{i-1,S,T}\)。
2025.10.17 wyh String & Ad-hoc
AT_agc072_a [AGC072A] Rhythm Game
按钮间较为独立,只有“占据时间段”的影响,所以我们把每个按钮刻画为“某时间区间内要完成某时长的工作”,每个时刻只能做一件工作。对按钮 \(i\),出发时刻 \(\in[T_i-X_i,T_i-X_i+D+0.5)\),耗时为 \(2X_i\),那么可以工作的区间为 \([T_i-X_i,T_i+X_i+D+0.5)\)。如果要用 \(0.5\),则每次把第一个开始 / 结束时刻为小数的区间向前调整为整数显然不劣,那么可将范围改为 \([T_i-X_i,T_i+X_i+D]\)。
记第 \(i\) 个按钮为 \([l_i,r_i],c_i\),\(l_i=T_i-X_i,r_i=T_i+X_i+D,c_i=2X_i\),则要在 \([l_i,r_i]\) 内连续完成时长为 \(c_i\) 的工作。
先考虑 \(\forall i,l_i=0\) 怎么做。由于所有工作都要完成,直接贪心,按 \(r_i\) 从小到大排序后依次处理工作,能处理完等价于有解。只需证明这样无法完成任务时必定无解:找到首个无法在时限内完成的工作,那么这段前缀的工作如何排序都无法完成;一段前缀的工作都无法完成,那所有工作自然更无法完成。另一种证法类似“邻项交换贪心”。
再考虑原问题。还是按 \(r_i\) 从小到大排序,先随便抓一个工作 \(i\) 来做。显然有 \(\forall 1\leq j<i,r_i\geq r_j\),即 \(T_i+X_i+D\geq T_j+X_j+D\),由于是同一个 \(D\),可以消掉,得到 \(T_i+X_i\geq T_j+X_j>T_j-X_j=l_j\),而 \(T_i+X_i=l_i+c_i\),是 \(i\) 最早结束的时间。这说明做完工作 \(i\) 后,所有 \(j<i\) 都可以做了。
和 \(l_i=0\) 时一样,我们先做一个 \(i\),再把所有未做的 \(j<i\) 从小到大都做了,贪心的正确性考虑调整——如果先做后面的工作,则与前面交换不劣。那么过程是将工作分为一段段处理,可以设计 DP:\(f_i\) 表示处理工作 \([1,i]\) 的最小结束时间。\(f_0=0\),转移时枚举 \(0\leq j<i\),先处理工作 \(i\),再从小到大处理工作 \([j+1,i]\)。则 \(f_i\leftarrow\max(f_j,l_i)+s_i-s_j\),\(s\) 是 \(c\) 的前缀和。刻画限制:\(\max(f_j,l_i)+c_i\leq r_i,\forall k\in[j+1,i-1],\max(f_j,l_i)+c_i+s_k-s_j\leq r_k\)。从大到小枚举 \(j\),过程中维护 \(\min(r_k-s_k)\) 即可。有解等价于 \(f_n\) 有值。
时间复杂度为 \(O(n^2)\)。
AT_agc068_b [AGC068B] 01 Graph Construction
相当于每个位置的上下两点连边、两个串的 \(0,1\) 对位连边。题目仅限制连通性,我们也只考虑连通性。
先令 \(S,T\) 分别为 \(n\) 个 \(0\) 和 \(n\) 个 \(1\),再往后一列列填:
- \(0,0\):将 \(S\) 的开头 \(0\) 挪到结尾。
- \(1,0\):连接并删除 \(S,T\) 的开头。
相当于有两个初始为 \(1,2,\ldots,n\) 的排列 \(p,q\),操作 \(1\) 是把 \(p\) 的开头挪到其结尾,操作 \(2\) 是连接并删除 \(p,q\) 的开头。那么任意置换都可以在 \(\leq n(n+1)\) 步中连出,且连完后上下 \(0,1\) 个数刚好分别相等。
题目给出了连通块,将每个连通块写成一个置换环即可。
AT_agc057_c [AGC057C] Increment or Xor
对 \(A\) 建低位 01-Trie,还原其逆排列(注意要蝴蝶变换)。\(+1\pmod{2^N}\) 相当于对最右侧的链交换左右子树,而 \(\oplus x\) 则是对若干层交换左右子树。
先强化操作找必要条件。对任意点交换左右子树包含原操作的决策,此时我们要求根的左子树与最终状态的左子树或右子树(交换得到)集合相同,需要交换则交换并打交换记号 \(tag\),再向下递归,直到叶子。如果存在一步不合法则无解,否则已知哪些点需要交换左右子树。
全局操作,先直接复合操作。\(\oplus\) 直接复合,没有的补 \(\oplus 0\),则任意操作序列都形如 \(\oplus,+,\oplus,+,\ldots,\oplus,+,\oplus\)(且可以给 \(\oplus\) 任意赋值)。还是不太好使,于是我们注意到 \(\oplus x,+,\oplus x\) 相当于把任意一条叶子的父亲到根的链左右子树交换(先把它换到最右侧,\(+\) 后再换回来,正确性在于两次 \(\oplus\) 操作的是同一批点,而同一点交换左右子树的操作有交换律,交换两次又会抵消)。那么任意操作序列都可以写成 \(\oplus x,+,\oplus x,\oplus y,+,\oplus y,\oplus z,+,\oplus z,\ldots,\oplus w,+,\oplus w,\oplus t\)(从前往后确定),表示进行若干次任意倒数第二层的点到根的链的左右子树交换(\(tag\leftarrow tag\oplus1\)),最后异或一次(这些操作也可以任意进行)。每个原操作序列对应一个新操作序列,而每个新操作序列都至少对应一个原操作序列。
最后一次异或能使所有 \(tag\) 清零,等价于除了叶子结点,每一层的 \(tag\) 要么全 \(0\),要么全 \(1\)。考虑倒数第二层,只有“变成全 \(0\)”与“变成全 \(1\)”两种方案,操作都是固定的,分别在 01-Trie 上模拟一遍即可(交换时真得交换,最后记得撤销)。
操作数最多 \(2^{n-1}\cdot3+1\),显然合法。
AT_agc071_c [AGC071C] Orientable as Desired
先尝试简单的构造,加强性质。令 \(\forall 1\leq i\leq n,X_i=0\),则不合法等价于可以定向使每个点入度或出度为 \(0\)。将入度 / 出度为 \(0\) 看做黑 / 白,则不合法等价于存在黑白染色,使黑白不相邻,也即原图是二分图。那么原图不是二分图的情况已经有解。
再尝试复杂一点的构造,将一个 \(X_u\) 变成 \([1,\deg_u]\)(其他还是 \(0\))。删除点 \(u\) 及与其相连的边后,每个连通块是一个连通二分图,对于不合法情况只有两种定向方式,此时 \(u\) 以外其他点都已满足入度或出度 \(=X_i\)。记每个连通块与 \(u\) 相连的边数分别为 \(d_1,d_2,\ldots,d_k\),则每个连通块对 \(u\) 的入度或出度贡献 \(d_i\)。入度或出度 \(=X_u\) 等价于能选出 \(d_i\) 的一个子集,使其 \(\sum=X_u\);由于 \(X_u\in[0,\deg_u],\deg_u=\sum_{i=1}^kd_i\),这等价于可以用 \(d_i\) 凑出 \([0,\sum d_i]\) 中的所有数。这个问题有经典结论:将 \(d_i\) 从小到大排序,则能凑出等价于 \(\forall 1\leq i\leq k,d_i\leq(\sum_{j=1}^{i-1}d_j)+1\)。于是可以枚举 \(u\in[1,n]\),用圆方树求 \(d\)(圆点 \(u\) 连向每个相邻方点内圆点的边数)来判断。
猜测仍未找到合法构造时无解,即证明此时对任意序列 \(X\),都有满足每个点入度或出度 \(=X_i\) 的构造。在以圆点为根的圆方树上自上而下处理,对当前圆点 \(u\),父亲方点(\(d_1\))已被定向,现在要定向其儿子方点(\(d_2,\ldots,d_k\))来满足 \(X_u\) 的限制。由于仅 \(X_u>0\) 时不合法,\(X_u\) 可被 \(d_1,d_2,\ldots,d_k\) 凑出,而现在限制一模一样(虽然固定了 \(d_1\) 贡献给入度还是出度,但 \(d_2,\ldots,d_k\) 贡献给入度还是出度都尚未确定,仍可以选择加不加 \(d_1\))。根是特殊的,但同理。所以此时无解。
AT_agc067_a [AGC067A] Big Clique Everywhere
团的边太多了,放到补图上看独立集。
注意到存在奇环则不合法,否则是二分图,任意左部点或右部点集合都是独立集,我们取点集中两者大的那个就可以,也就是不存在奇环则合法。
补图边多,怎么黑白染色?找关于数量的必要条件,显然原图要存在一个大小为 \(s=\lceil{n\over2}\rceil\) 的团,即 \(m\geq{s\choose2}\)。此时 \(m\) 与 \(n\choose2\) 仅有常数倍差距,而补图边数 \(m'={n\choose2}-m\leq{n\choose2}\approx m\),于是正常做的时间复杂度为 \(O(\sum(n+m))\)。
类似问题。
AT_agc058_c [AGC058C] Planar Tree
要尽量构造出满足条件的树。每次连边相当于对环进行一次划分,所以我们考虑相邻点的性质来简化问题。
- 相邻同色点(\(A_u=A_v\))可以合并(),一个方案不产生“横跨”等价于它在合并后也不产生“横跨”。
- \(2\) 的性质好于 \(1\)、\(3\) 的性质好于 \(4\),所以可以将相邻的
AT_agc023_d [AGC023D] Go Home
打不过就加入。
有很多栋楼的居民时难以讨论,故讨论最终的情况(较简单),再尝试归纳到之前的子问题。
先将楼按 \(X\) 从小到大排序(题目帮忙排好了),则整个过程形如往一边走一截,再折回另一边走一节,再折返……不断扩展整个“走过”的区间,直到扩展至 \([1,n]\)。
特判 \(n=1\)。考虑 \(1,n\) 两栋楼,有一栋最后到,另一栋会在之前抵达,且到它之后直接到另一栋楼,考虑 \(X_1<S<X_n\) 时它们居民的决策:
- 车往左走当且仅当 \(P_1\geq P_n\)。对 \(P_1\geq P_n\) 的情况考虑反证,到 \(n\) 之前一定有左边一段后缀的居民未下车;\(P_1<P_n\) 同理。
尝试归纳至子问题。秉持着“打不过就加入”的原则,若 \(P_1\geq P_n\),则在车到达 \(1\) 之前 \(n\) 的居民都会跟 \(1\) 投一样的票,用以加速这个过程。于是我们删除 \(n\),令 \(P_1\leftarrow P_1+P_n\),待删除 \(1\) 后直接从 \(1\) 走到 \(n\) 结束。\(P_1<P_n\) 同理,故我们可以归纳至 \([2,n]\) 或 \([1,n-1]\)。
注意前面的讨论全部建立在 \(X_1<S<X_n\) 的前提下,\(S\leq X_1,S\geq X_n\) 的情况即为边界,此时一直向左 / 向右走即可。
考虑如何计算路程。整个过程是一段一段的(向左 / 右,向右 / 左,向左 / 右……),只需计算每一段的路程。考虑递归的过程,第一段是递归边界的 \(X_r-S\) 或 \(S-X_l\),而其他段是非边界的当前结点(\([l,r]\))与其上一层“先删”的位置不同时(包括 \(l=1\wedge r=n\))的 \([X_l,X_r]\)。于是可以在递归时直接计算。
AT_agc066_a [AGC066A] Adjacent Difference
网格图相邻限制,先黑白染色转为二分图限制。
这个问题和奇偶性强相关,构造时可以往奇偶性的方向想。黑白染色、分配奇偶都有两种方式,题目限制又有 \(1\over2\) 的系数,联想到鸽巢拼盘。
我们令黑格为 \(d\) 的奇数倍最近的数,白格为 \(d\) 的偶数倍最近的数,则一定合法,且两种染色方案代价之和恰为 \(n^2d\),那么其中一定存在一种方案代价 \(\leq{n^2d\over2}\)。
为了实现方便(避免出现负数),可以先将所有数 \(+1000\),输出时再减去。
AT_agc066_c [AGC066C] Delete AAB or BAA
套路:先找删空一段区间的充要条件,再做区间划分 DP。
- 这个条件的范围包含所有“极小可删除区间”,不包含任何“不可删除区间”,而每个“非极小可删除区间”包不包含都可以。
先找必要条件:只考虑数量关系而不考虑位置,\(cnt_A=2cnt_B\)。
继续加强条件,考虑子问题:
- 反着插入。首先 \(n=3\) 时有且仅有 \(AAB,BAA\) 满足限制,接着向其中插入 \(AAB\) 或 \(BAA\)。
- 正着删除。我们每次删去一个 \(AAB\) 或 \(BAA\),归纳至 \(n-3\) 的子问题。
考虑何时能删除一个 \(AAB\) 或 \(BAA\)。我们只需找到 \(1\) 个 \(B\),其一侧与 \(2\) 个连续的 \(A\) 相邻,一个 \(B\) 好找,那我们想有足够多的 \(A\)(虽然数量上够了,但 \(1A,2B\) 的位置关系中有且仅有 \(ABA\) 删不了)。
咋办呢?用“极小”来加强性质。自然想到插入时不能插在首尾(否则可分成两段分别删除),那么首尾必是 \(1A,1B\)(必要条件)。现在中间有 \((2k+1)A,kB\ (k\geq0)\)。
- \(k=0\) 时显然可删空。
- \(k\geq1\) 时:先把 \(kB\) 排成一排,再插入 \(A\)。不看整个串的首尾,相当于有 \(k+1\) 个盒子,不出现 \(AAB/BAA\) 等价于每个盒子放 \(0/1\) 个 \(A\),但 \(k+1<2k+1\),所以存在一个盒子放了 \(\geq2\) 个 \(A\),可删除(且不影响首尾)。
于是可以归纳证明充分性。现在充要条件即为:\(cnt_A=2cnt_B\),且首尾是一个 \(A\) 一个 \(B\)。
我们再刻画 \(cnt_A=2cnt_B\):设 \(A,B\) 的权值分别为 \(-1,2\),\(s_i\) 表示其前缀和,则区间 \([l,r]\) 满足 \(cnt_A=2cnt_B\) 等价于 \(s_r=s_{l-1}\)。
由于每次删的个数相同,可以将“最多删多少次”转为“最少剩多少个”。设 \(f_i\) 表示 \([1,i]\) 的答案,则转移有两种(\(c\) 表示字符串):
- \(f_i\leftarrow f_{i-1}+1\)
- \(f_i\leftarrow f_j\ (0\leq j<i,s_i=s_j,c_i\neq c_{j+1})\)
初值为 \(f_0=0\),答案为 \(n-f_n\over3\)。将 \(s\) 离散化后,用桶 \(g_{V,0/1}\) 优化即可。时间复杂度为 \(O(n\log n)\)。
浙公网安备 33010602011771号