冬月做题记录

Last Dance?


11.02

P14362 [CSP-S 2025] 道路修复 / road

什么你问我为什么这道题不放在 11.1 因为我特么没场切啊。

显然 \(m\) 诈骗吧,只保留最小生成树就行,枚举每个特殊点状态然后 Kruskal 可以做到 \(O(2^knk\log(nk))\),然后赛时就止步于此了,然而只需要把所有边预先排个序就可以把那个 \(\log\) 去掉。

如果你牺牲一点空间存每个状态的所有边然后每次从上一个状态 \(O(n)\) 归并一下可以做到 \(O(2^kn)\)

P14363 [CSP-S 2025] 谐音替换 / replace

什么你问我为什么这道题不放在 11.1 因为我特么没场切啊。

多模匹配一眼 AC 自动机吧,匹配条件一眼要求 \(S_1S_2\) 前后缀相同部分与中间的不同部分分别同 \(T_1T_2\) 相应部分相同吧。怎么会有奶龙想出直接合并两个串达到 \(26^2\) 的字符集然后硬上 AC 自动机然后直接爆零呢。

考虑把每个字符串对用如下方式存入自动机:\(\texttt{A#BC#D}\)\(\texttt{AD}\) 是前后缀相同部分,\(\texttt{#}\) 是特殊字符,\(\texttt{BC}\) 表示两串不同部分连在一起,然后直接跑多模匹配就行了啊。空间完全够的。

11.03

AT_arc068_d [ARC068F] Solitaire

简单转化一下就是要求可以划分成两个不降序列并给定 \(1\) 的位置的方案数。

显然 \(k\) 之后的部分是可以额外计算的。考虑 \(k\) 之前的部分,由于要去重,因此需要钦定构造方式尽可能倾向一个序列。不难发现直接计数要枚举的有点多所以设计 DP 解决,事实上利用性质正确钦定构造方式之后状态和转移方程都很简单。

CF1149C Tree Generator™

首先这个东西显然得想办法放到序列上解决。一个关键且简单然而我没想到的东西是 \(dis(x,y)=dp(x)+dp(y)-2dp(lca(x,y))\)。然后 \(dp(x)\) 是容易得到的,令左括号 \(+1\) 右括号 \(-1\),那么 \(dp(x)\) 就是 \(x\) 位置的前缀和。通过 \(O(1)\) LCA 方法可以联想到 \(dp(lca(x,y))\) 就是区间最小值。

放线段树上维护这个东西即可。但是区间最小值貌似不很好维护。这时候我们发现如果最小值偏大必然更劣,因此只需要分别维护两边到边界的最小值两种方案取最大值即可。又是这种不合法不优的典 trick。

P4425 [HNOI/AHOI2018] 转盘

首先你发现显然只会在起点停留不劣。然后你发现只会走一圈,不然你按住结束点不动然后把起始点移动直到没有重合部分并延后出发时间,你发现显然是等价的。

因此我们就是要求最小的出发时间。列出来就是 \(\min\limits_{i=1}^{n}\max\limits_{j=i}^{i+n-1}(T_j+i-j)+n-1\)。然后又是那个典爆了的不合法不优。你发现如果越出 \(i+n-1\) 的话会与之前重合,然后 \(T_{i+n}-(i+n)<T_i-i\),因此直接变成 \(\min\limits_{i=1}^{n}(\max\limits_{j=i}^{2n}(T_j-j)+i)+n-1\)

这个东西放线段树上维护即可。不带修是简单的。考虑修改,单侧递归即可,回溯时搜左子树更新,也就是二分最后一个被更新点影响的位置。

CF212D Cutting a Fence

单调栈处理出每个点作为最小值的左右边界,然后每次直接枚举小的那一侧区间端点就行。这样搞复杂度同启发式合并,是 \(O(n\log n)\) 的。

P4340 [SHOI2016] 随机序列

诈骗题。发现只有最前面的连续乘积有贡献,其他都会抵消掉。线段树直接维护就行。

P4898 [IOI 2018] seats 排座位

事实上是今年 10-29 做的但今天又拉了一遍。

考虑描述一个矩形时的状态。一个好用的充要性质为只有一个黑点满足左上均非黑点,且不存在白点四联通至少两个黑点。这个比较巧妙所以貌似归纳不出什么普遍规律。然后对时间轴线段树维护满足这两个性质的点数,然后就是数几个时间这两个数之和为 \(1\) 即可。

11.04

BK52077 [校模拟赛 Round 31] 图

没找到原题。大意是求给一个无向完全图赋 \([1,L]\) 内值作为边权使得 \(1\rightarrow n\) 最短路长 \(k\) 的方案数。\(n,k\le 13,L\le 10^9\)

赛时想出了递归处理路径方案数然而并无用。考虑直接刻画图状态,升序搜索每种最短路长度的点数,然后组合数计算一下即可。复杂度是 \(O(\binom{n+k}{n}(n+k))\)

BK52078 [校模拟赛 Round 31] 路线

加强自 AT_arc136_e [ARC136E] Non-coprime DAG,加强了单点修改操作。

赛时想到了分讨质数合数然而并无用,应该分讨奇数和偶数。事实上只能最多一个偶数,奇数假如满足增减各自最小质因子后仍不相交就不能同时选,然后就可以枚举交点得到交于此处的最大的奇数值和与可能的偶数值,变成区间覆盖使用线段树维护即可。

BK52079 [校模拟赛 Round 31] 魔术师

加强自 CF1210F2 Marek and Matching (hard version),加强了数据范围,\(n\le 9\)

使用霍尔定理,然后图计数题我也不知道怎么写做题记录,本题的关键思想就是找到条件使每个不合法状态有唯一的代表元以供容斥枚举防止重漏,具体的详见题解

P4559 [JSOI2018] 列队

一个显然的东西就是选出一些人之后,肯定是按位置顺序依次走到对应位置上,也就是相对位置不变。但是编号连续不一定位置升序,直接维护就很不好搞,考虑使序列升序,主席树差分时间轴即可,然后线段树上二分拆绝对值。

[BZOJ 十连测] 可持久化字符串

首先循环节就是串长减去 border 长,因此就是实现 KMP 算法。直接维护每个点的 \(nxt\) 每次暴力跳复杂度是假的,但很有趣的一点是我们可以利用 border 和循环节的性质实现每次只跳 \(\log\) 次。

如果 border 长度不超过当前串长一半,直接跳即可,长度减半;否则,此时 \(j\) 前缀必然是循环节为 \(j-nxt_j\) 的循环串,当前不行,循环串内对应位置都不行,因此直接跳到最后一个循环节内,也就是跳到 \(j\bmod (j-nxt_j)\) 处。这样每次匹配就只会跳 \(\log\) 次。

由于是在树上跳跳跳因此还要写个倍增。具体实现起来如果不很熟悉 KMP 和循环节的话还是有点痛苦的。

11.05

BK52082 [校模拟赛 Round 32 开拓者杯] 列车扫除

赛时一开始猜的数量只有 \(0,1,>1\) 三种,然后开始大力分讨,分讨到 \(3\) 发现不对貌似是个无限递归的东西,归纳一下得到只有三种情况:三个全部相等、两个相等且第三个更大、存在唯一一个最小值。

第三个需要拆成三部分,第三部分是两个等差数列每项相乘求和的东西,可以拆成一个常数项一个等差数列和一个平方数列,然后我忘了平方数列怎么算才想起来可以直接由所有情况容斥直接得到第三种情况的方案数。

本来虽然有点恶心还可以接受,但这一坨还得开 __int128 我就只能骂崩批收收味了。

BK52083 [校模拟赛 Round 32 开拓者杯] 换来换去

题意转化之后是求将 \(n\) 个有编号物品划分入任意个大小 \(>1\) 的无编号集合的方案数,就是 P5748 集合划分计数加强了一个集合大小不为 \(1\) 的限制。

赛时一开始想了一个可重集排列做法,大概是 \(\sum\frac{n!}{k!\sum\limits_{i=1}^ka_i}\),然后这个东西因为阶乘的限制 DP 就卡在 \(O(n^3)\) 了。然后考虑暴力一点每次钦定首位所在组转移,则有 \(f(i)=\sum\limits_{l=2}^i\binom{i-1}{l-1}f(i-l)\),同理这个做法也卡在 \(O(n^2)\)。DP 显然没有优化前途了,于是考虑容斥,然后根本想不到怎么容斥笑死。不会斯特林数导致的。

答案可以如下表示:\(\sum\limits_{m=0}^n(-1)^{n-m}\binom{n}{m}\sum\limits_{k\ge 0}{m\brace k}\),含义就是钦定一些点单独为一个集合(赛时坚决认为这不可做哈哈)。推一下式子:

\[\begin{aligned} &\sum\limits_{m=0}^n(-1)^{n-m}\binom{n}{m}\sum\limits_{k\ge 0}{m\brace k}\\ =&\sum_{m=0}^n(-1)^{n-m}\binom{n}{m}\sum_{k= 0}^m\sum_{i=0}^k\frac{(-1)^{k-i}i^m}{i!(k-i)!}\\ =&\sum_{m=0}^n(-1)^{n-m}\binom{n}{m}\sum_{i= 0}^m\frac{i^m}{i!}\sum_{k=i}^m\frac{(-1)^{k-i}}{(k-i)!} \end{aligned} \]

发现 \(k\) 上界设做 \(m\) 很不方便,直接放缩到 \(n\),然后式子可以改写成:

\[\begin{aligned} &\sum_{m=0}^n(-1)^{n-m}\binom{n}{m}\sum_{x+y\le n}\frac{1}{x!y!}(-1)^yx^m\\ =&(-1)^n\sum_{x+y\le n}\frac{\sum\limits_{m=0}^n\binom{n}{m}(-x)^m}{x!}\frac{(-1)^y}{y!}\\ =&(-1)^n\sum_{x+y\le n}\frac{(1-x)^n}{x!}\frac{(-1)^y}{y!}\\ =&\sum_{x+y\le n}\frac{(x-1)^n}{x!}\frac{(-1)^y}{y!} \end{aligned} \]

中间那一步 \(x!\) 上面是二项式定理直接变化的。最后这个形式就可以前缀和 \(O(n)\) 求了。然后 \((x-1)^n\) 需要每组数据线性筛预处理一下。复杂度 \(O(n)\)。应该还有贝尔数生成函数做法这里就不写了。

是一道不错的组合数学题,但是你放在 NOIP 模拟赛 T2 是何意味呢?

CF1401E Divide Square

一个显然的想法是一个线段与另外的线段相交就会产生新的区域,然后深入一点,答案其实就是各个线段的交点数加上横跨 \([0,10^6]\) 的边数加 \(1\),求交点数是简单的,离线扫描线一下即可。

CF283E Cow Tennis Tournament

两点之间的连边只受包括两点的操作数奇偶性影响。考虑钦定住一个点找要求的三元环,发现这样还要求另外的两点之间的连边方向,很不好做。考虑正难则反,找不合法的三元环数量,那么显然只要找那个出度为 \(2\) 或者入度为 \(2\) 的即可。扫描线就可以找出每个点一侧的正向边数,正反两遍扫描线即可。

11.06

CF407E k-d-sequence

等差数列的性质很显然吧,满足所有数同余且不重复即可,加入至多 \(k\) 个数的限制可以写作 \(\max(\lfloor\frac{a}{d}\rfloor)-\min(\lfloor\frac{a}{d}\rfloor)+1-(r-l+1)\le k\)。找到原序列上每个数合法的左边界满足全部同余且不重复是简单的,那么就是要对每个数的边界内找到最小的满足上述条件的 \(l\)

改写条件可以写作 \(\max-\min+r\le k+r\),直接维护这个东西很不好做,如果转权值线段树的话问题本质没变并没有用。然后发现可以在外面独立维护 \(\max,\min\),额外开两个单调栈即可,这样线段树只需要维护区间加就行。

GYM102979C Colorful Squares

考虑一个点作为右下角,那么每个颜色都可以选出最近的一个点,但是这样的话边长是个 \(\max(\max(dis_x,dis_y))\) 状物,很不好维护。如果扫描右坐标 \(r\) 的话满足条件的 \(l\) 需要满足存在一个长为 \(r-l+1\) 的区间包含了所有 \(k\) 种颜色,维护困难。

最优化边长不很可做,考虑二分答案转为判定性问题,那么边长一定,扫描 \(r\) 时只需要看当前轴上是否存在一个点作为右上角其矩形可以包含 \(k\) 种颜色,那么 \([r-len,r]\) 横坐标区间内每个点都只会给纵坐标上一段区间的矩形产生贡献,直接区间加即可。由于一个颜色有多个点可能算重,开个 multiset 维护一个颜色所有点的纵坐标。

P5816 [CQOI2010] 内部白点

一个新增的黑点左右上下必然都有黑点,因此只需要考虑原来的黑点判定。所以如果给相邻黑点连线就是求交点数量,扫描线一下就做完了。

HDU5770 Treasure

分讨一下给出路径两端点的祖先关系,形式均为起点或终点在或不在一个子树中。拍成 DFS 序的话就是要求在 \(O(1)\) 个区间内。考虑拉成二维,贡献形式就是 \(O(1)\) 个矩形加,离线扫描线即可。特殊的,对于两点相等的情况,直接搞操作是在 \(O(n^2)\) 的,因此考虑把这种操作的贡献累加到点,合并同一个点的所有操作,操作就降到 \(O(n)\) 级别。

CF997E Good Subsegments

翻译一下题意,好序列的要求就是 \(\max-\min=r-l\)。和 k-d-sequence 一个套路地,考虑枚举右端点并单调栈独立维护 \(\max,\min\) 信息。但现在要求恰好相等,\(\max-\min+l=r\) 就很不好维护,改写成 \(\max-\min+l-r=0\) 就可以了,因为这个值必然非负,因此我们只需要维护最小值信息。

但现在我们要求一段区间内的子区间答案,转化为历史信息和,可以等价于,我们要对 \([l,r]\) 内所有数值为 \(0\) 的次数求和。事实上我们只需要实现给当前线段树中所有为 \(0\) 的位置答案 \(+1\),额外打个 tag 就可以实现,下传的时候判断子节点最小值是否与当前节点最小值相等即可,之所以不判 \(0\) 是因为可能在打 tag 之后有区间修改操作改变了最小值。

P8868 [NOIP2022] 比赛

一个区间的答案显然就是 \(\max(a)\max(b)\),用同样的方法扫描 \(r\) 然后单调栈独立维护 \(\max\) 即可。然后又是子区间问题,也就是求历史信息和,然后就没了。维护历史信息心得额外开一篇写吧。

11.07

P3246 [HNOI2016] 序列

比赛严格弱化版。

BK29854 Arithmetic

和 CF407E k-d-sequence 一个东西,转化之后就是要维护区间内所有合法子区间的 \(\max-\min-r+l\) 的和。直接维护历史信息和即可。特殊地,每次统计历史信息时,只更新到当前 \(r\) 合法的左边界即可,更左边的不合法左边界直接不计入答案。

P9990 [Ynoi Easy Round 2023] TEST_90

简单区间历史和题。看到子区间同理考虑扫描线维护历史信息和,不难发现我们要维护的其实就是区间异或操作与区间为 \(1\) 的位置数,以及后者的历史信息和。还是很好设计的,码量相对也很小。

P9991 [Ynoi Easy Round 2023] TEST_107

历史信息和过量了,往历史信息和思考许久无果,考虑答案性质,发现实际上就等价于钦定不包含某种颜色找最大的子区间,那么只有三种情况:两个同颜色点之间,区间内某个颜色最后一个点后面到区间结尾,区间内某个颜色首个点前面到区间开头。分讨三种情况,前两种各自可以简单扫描线做,第三种直接做不方便考虑倒着扫变成第二种,线段树维护对应点作为另一个端点的答案即可。直接扫三遍可能需要略微卡常。

CF571D Campus

首先看到合并条件容易想到并查集吧,由于要维护路径关系所以考虑按秩合并,那么单次跳祖先是 \(O(\log n)\) 的,那么查询实际上就是要求当前点在第一个并查集上,到祖先的每一个点,在查询点最后一次清空之后且路径全部连上之后,加权操作的总和,对每个点开个数组维护前缀和,每个点二分找后缀统计答案即可。注意只关心查询点最后一次清空之后,祖先点如果提前清空了不用管。找清空时间直接跳第二个并查集即可,注意操作时间也要满足路径已经全部连上。

11.08

BK52099 [校模拟赛 Round 34] 国王的试炼 / CF1542D Priority Queue

直接刻画整个状态有点困难,考虑把贡献下分至点,加操作产生的贡献显然,一个点被删除操作影响到当且仅当他当前在序列中且恰好为第 \(k\) 位。发现 \(n\le 500\),直接设计 DP,\(f(i,j,k,l=0/1)\) 表示考虑前 \(i\) 个操作数 \(j\) 排在第 \(k\) 位的方案数,\(l\) 表示这个数现在是否存在。转移是简单的,然后发现只需要滚动一下就做完了。

BK52100 [校模拟赛 Round 34] 灯光秀 / CF1545C AquaMoon and Permutations

不难想到建图,连边表示互斥,那么就是个图上最大独立集状物,显然不可做。然后感觉还原出原配对之后貌似可以贡献预先计算搞个困难 DP,但是还原配对貌似是个一般图最大匹配状物,然后赛时就死这了。

因此必须从建图模型之外特殊的性质入手了。考虑对于一列,假如存在数字只出现了一次,那么它那一行必选。假定我们这样选出了 \(k\) 行,然后把与它们冲突的行删掉,那么由于配对所以至少删了 \(k\) 行,那么还剩下 \(2n-2k\) 个可选的行。同时,对于每一列,这一列剩下的 \(n-k\) 个数都出现了至少两次,因此每个数字都出现了恰好两次。

现在限制就变成了二选一状物,新的性质建图连边之后就是个黑白染色状物,答案就是 \(2^k\)\(k\) 表示联通块个数。最小字典序的话就直接在满足性质的条件下从小到大选就行了。

BK52101 [校模拟赛 Round 34] 促销活动

区间 \(p\) 加,单点覆盖 \(q\),查询区间 \(\max(pq)\),纯数据结构题。发现区间加对整个区间最大值的影响是复杂的,分析一下发现每个点的贡献都是一条直线,一个区间整体信息可以使用凸包维护,横轴就是区间加的懒标记。上线段树的话因为无法快速合并凸包而炸掉,考虑分块,复杂度就可以做到 \(O(n\sqrt n\log\sqrt n)\)

\(n\le 10^5\)\(1s\) 本地跑 \(1.5s\) 我还以为是错解,你告诉我正解就是这个?赛后你再告诉我你把时限改到 \(2s\) 然而我的代码在你评测机上只跑了 \(0.6s\) 是不是太幽默了?

11.10

P9196 [JOI Open 2016] 销售基因链 / Selling RNA Strands

和谐音替换一个东西吧,考虑一个匹配串复制一遍中间加个特殊字符,然后就能上 ACAM 了。每个点存以此结尾的模式串编号暴力下传即可,复杂度是 \(O(\sum|S|)\) 的,这是因为 fail 链上串长递增,因此链长只有 \(O(\sqrt {\sum|S|})\) 级别。

AT_agc002_d [AGC002D] Stamp Rally

二分答案之后就是判断当前二者联通块大小和,特判一下位于同一联通块的情况,可持久化并查集即可。\(O(n\log^3n)\)

CF1659E AND-MEX Walk

首先考虑怎么判 \(\mathrm{mex}=0\),只要存在一条路径,满足其中一位全部为 \(1\) 即可,这个可以并查集维护。

然后考虑怎么判 \(\mathrm{mex}=1\),首先已经不存在一位均为 \(1\) 的情况了,那么只要存在一条路径使得倒数首个非 \(0\)\(>1\) 即可,也就是说第 \(0\) 位最后一个为 \(1\) 的位置其他位存在 \(1\)。那么只需要存在一个非第零位全是 \(1\) 的路径能走到一个点,使得这个点有一条末位为 \(0\) 的连边即可,因为走这条边之后第零位变成零,而在此之前的路径上有一位均为 \(1\),符合条件。把这种边两个端点连向一个虚点然后判断起点是否与虚点连通即可。

然后发现 \(1,2\) 不可能共存,因此答案只有 \(0,1,2\) 三种。

P4768 [NOI2018] 归程

发现每次终点都是一定的,因此可以预处理出每个点的最短路长度。那么我们只需要在开车能到达的点中找到最短路最小的一个即可,这个可以可持久化并查集实现。简单优化可以做到 \(O((n+m)\log n+q\log^2n)\)

P6018 [Ynoi2010] Fusion tree

首先所有相邻的点不太好做,我们考虑维护子节点信息,然后单独处理父节点。现在我们需要对每个点支持:单点修改、全局加、全局异或和查询,特殊地,全局加只加 \(1\)。考虑上 trie,每个节点维护子树内数量与异或和,转移是简单的。考虑全局加 \(1\) 的意义,就是结尾一段连续的 \(1\) 变成 \(0\),后一个 \(0\) 变为 \(1\),因此考虑从低到高维护 trie,每次交换儿子节点并向原 \(1\) 子节点递归进去。

P14387 [JOISC 2017] 火车旅行 / Railway Trip

首先容易想到,每个点与两侧最近的不小于他的点连边,然后跑最短路即可得到答案。考虑最短路径的形式,必然是从等级小的点,走到一个等级最大的点,然后再走向等级更小的点,这样一个峰状。因此我们可以视作是两边同时向峰巅汇集。

考虑分讨三种情况:

  • 若最大点在二者中间,那么二者会在各自一侧最少步数走到这一点;
  • 若一侧经过了二者中间的最大点,然后二者在另一侧外的更大点汇聚,显然这个更大点应该是这一侧外首个超过中间最大值的点;
  • 若二者都先走到了各自一侧外更大点,然后不经过中间最大值直接汇集,那么显然两侧的更大值都应该是最近的超过中间最大值的值。

整合一下,发现每一侧都是要么走到中间最大值,要么走到外向首个超过中间最大值的点。

我们先从左侧点跳尽可能多的步数,使得当前步数左侧点不可能走到右侧点以右,那么现在要么跳到了中间最大值,要么跳到了外向更大值处。

然后从右侧点跳尽可能多的步数,使得当前步数右侧点不可能走到左侧点跳到的位置以左。事实上只需要不可能走到左侧点可能跳到的最右侧位置以左即可,假如左侧点往中间跳显然对,假如往另一侧跳那么右端点不会到中间最大值,右侧点会走到中间最大值处或者外向更大值处。

因此倍增跳就行。显然从区间端点跳不劣于非端点跳转移,因此倍增转移时只用考虑端点即可。

P5666 [CSP-S 2019] 树的重心

首先不难想到枚举重心计算多少种断边方案符合,由于重心性质,只需要满足删去的部分大小在一个范围内即可。直接做也可以,但是要容斥一下并离线扫描线。

先得到原树一个重心然后以其为根,那么非根节点断边必然不在其子树内,因此我们只需要得到在其子树外的范围内的边即可,另外开一个树状数组用来计算搜索顺序前缀各子树大小个数,然后差分得到子树内的点,然后用当前全局答案减去这些子树内的答案即可。

特判根节点,删边若在重儿子子树内,则删去部分不超过 \(n-2S'\)\(S'\) 为次儿子大小。此外同理减去二倍重儿子大小。直接深搜一遍即可。

CF1783G Weighed Tree Radius

难点在不带修怎么求所谓半径。

半径是个有向的东西,很不好做,考虑转化为直径状物,考虑求 \(a_u+a_v+dis(u,v)\) 的最大值,考虑给每个点挂两个长 \(a\) 的链,这样上述问题就转化为了树的直径。之所以挂两条是为了处理 \(u=v\) 的情况。

我们证明答案即为 \(\lceil\frac{\max(a_u+a_v+dis(u,v))}{2}\rceil\)。由树的直径的性质,一个点的所谓偏心距必然是到直径一端的距离。因此要最小化这个东西选取的点必然为直径上的中点。其次,这个点必然在原树上,否则 \(u=v\) 更优。原树上边权全为 \(1\),因此可以取到一半上取整。

考虑带修,首先直径是可以合并的,一个两个点集合并形成的点集的直径,端点必然是原先两个点集直径四个点中两个,因此考虑上线段树,每次暴力枚举合并即可,使用 \(O(1)\) LCA 可以做到 \(O(n\log n)\)。其次,修改的是两个叶子节点,只需要改其自己的树上差分值即可。

11.11

CF516D Drazil and Morning Exercise

首先必然会走到直径的一个端点。然后很巧妙的一点是,如果我们找出最大距离最小的那个点作为根,那么树的 \(f\) 随深度递增。那么考虑对每个点存以其为最小值的答案,就只需要考虑其子树中的点,每个点贡献给其祖先的一段后缀,二分找到最高的满足条件的祖先然后差分即可。

P3899 [湖南集训] 更为厉害

考虑 \(b\)\(a\) 下方的情况,就是满足 \(dp_b\le dp_a+k\)\(\sum(sz_b-1)\)。放到 DFS 序上之后就是二维数点,离线扫描线即可。其他情况省略。

LOJ6029 「雅礼集训 2017 Day1」市场

据说硬做貌似也可以,存在一道 AT 的题。但这里还是考虑势能做法。一个粗略的想法是至多除 \(\log\) 次,但是由于区间加这个就炸了。然而单点加是可以的。考虑一个序列的极差,一次除法会使得极差至少除二,且只有区间端点会增加额外的势能。那么对于一个 \(v-\lfloor\frac{v}{d}\rfloor\) 全部相等的区间,区间除可以转化为区间加,否则暴力递归下去即可。

CF600E Lomsat gelral

启发式合并。

P4149 [IOI 2011] Race

启发式合并,对每个点记键和值的偏移量即可,实现起来有点绕。注意更新的时候不能直接取 \(\min\),若原来没有这个值要直接赋值,否则不存在的值初始化为零会出错。值得注意的是,洛谷数据很水所以这里错了也能过。

CF375D Tree and Queries

启发式合并,再开一个数组存出现次数 \(\ge x\) 的颜色数即可,每次至多更新一个值。

11.12

CF1797F Li Hua and Path

加点是简单的,考虑如何得到初始答案。考虑建出两个重构树,一大根一小根,分别得到二者的答案(每个节点的子树大小减一之和),然后考虑容斥掉不合法情况,枚举节点看当前节点的祖先有多少是另一棵树上的子孙即可,利用 dfn 即可实现。

P4223 期望逆序对

一个比较关键的发现是,对于一对数,除了他们各自初始所在的位置外,其他所有位置都是等价的,因此他们操作结束后的位置情况事实上只有七种,可以矩阵快速幂快速转移。得到每种状态的方案数之后考虑计算每个点对中原右侧点的答案,对七种情况分别推式子即可。

P14269 [ROI 2015 Day2] 警报系统

一个暴力做法是,对于每个点,将其向其可以触发的点连有向边,最后答案就是入度为零的 SCC 数。考虑优化建图,发现每次连边都是给一个距离前缀连边的形式,因此想到前缀和优化建图,然而图上并不方便直接找到与每个点距离前缀的链。

考虑点分治,每个分治块中所有点按分支中心距离升序排序得到一条虚链,然后对分治块中每个点都二分找到这条虚链上可连接的前缀连边。这样连出来的边数是 \(O(n\log n)\) 级别的。同一子树中的距离虽然会算错,但只大不小不会影响正确性,因此直接连即可。

值得注意的是,最后算答案时,一些没有被经过过的虚点应当删去,从所有实点搜一遍即可找出要被删除的节点。

最后,时空限制对于我这种大常熟选手来说还是有点紧了。qwq

11.13

BK52113 [CQ 友谊赛] 数码串 / P13046 [GCJ 2021 Finals] Divisible Divisions

不难想到前缀和优化 DP,但是没有逆元就很不好搞,然而发现 \(10\) 的因子很少,可以将 \(d\) 表示成 \(2^x5^ym\),然后区间长度超过 \(\max(x,y)\) 之后余数就只与 \(m\) 有关了,不超过的暴力跑即可。

BK52114 [CQ 友谊赛] 背包

矩阵快速幂就做完了。每次查询要用向量乘优化不然复杂度很假。最后复杂度 \(O(w^3\log V+qw^2\log V)\)

BK52115 [CQ 友谊赛] 圆环 / CF1996G Penacony

一个关键性质是,钦定断开一条边之后,所有路径都是固定的……因此直接枚举断边即可,路径总变化次数是 \(O(p)\) 级别,然后上线段树无脑维护一下线段并最后特判一下全选的情况就做完了。

你 T3 放道签蓝 T1 放个紫是何意味?说好的友谊赛信心赛呢?被你附吃了吗?/fn

P3242 [HNOI2015] 接水果

首先利用 DFS 序转序列问题,然后变成对一个点查询覆盖了它的第 \(k\) 大矩阵权值问题,离线扫描线直接上树状数组套权值线段树二分即可。\(O(n\log^2n)\)

11.14

P5025 [SNOI2017] 炸弹

不难想到线段树优化建图吧。但是 DAG 可达点数统计不可做,由于这道题每个点连向一个区间,所以可以维护区间左右端点。

P3588 [POI 2015 R2] 沙漠 Desert

考虑建图,连边表示偏序关系,然后就是简单贪心。但直接连边肯定不行,考虑线段树优化建图,但每次都是 \(k\) 个点对 \(O(k)\) 的区间连边,直接连还是会炸,发现每个点连向的区间都是一样的,考虑每次新建一个虚点,然后这些点连向虚点、虚点连向这些区间即可。

P6822 [PA 2012 Finals] Tax

一个粗暴的想法是直接拆点然后前后缀优化建图,然而空限太小会炸。考虑化边作点,正反向边互连原边权的边,同一点的所有出边,小到大连边权差值,大到小连无权边,然后开个源汇点处理起点和终点,就可以跑最短路了。

LOJ6177 「美团 CodeM 初赛 Round B」送外卖2

发现数据范围很小,不难想到状压,然后对领到的外卖和送到的外卖都开一维再加一维当前位置存最小时间就能 \(O(n^22^{2q})\) 飞过去了。这样过不去原题,三进制压一下空间即可。

LOJ6515 「雅礼集训 2018 Day10」贪玩蓝月

是一个貌似比较典的 trick,以前见过几次。

如果没有加入删除操作的话,就是一个基础背包。考虑维护加入删除操作,可以维护两个栈栈尾相接,每个节点维护自己到栈位的背包信息,单次插入是 \(O(p)\) 的,删除直接弹出即可,如果一侧已经空了就从另一侧挪一半过来重构,这部分挪点总量均摊一下是 \(O(n\log n)\) 级别。每次单点查询 \(O(p)\) 合并两端信息即可。

对于本题每次查询前预处理一个 ST 表就能做到 \(O(np\log n)\) 的复杂度。

P3780 [SDOI2017] 苹果树

关键在于转化题意,题意等价于选定根为一端的一条路径,不计代价地选择路径上每个点各一个苹果,然后在剩下的苹果中满足依赖性质地选择至多 \(k\) 个,求最大价值。

然后不难想到这条路径在叶子结尾显然不劣。于是我们可以把树分为三部分:路径左侧的点,路径右侧的点,以及路径上的点。先序后序各遍历一遍做树上依赖性背包即可,可以将路径上的点与路径左侧的点合并,然后路径上的个数视作 \(a_i-1\) 跑,离开节点更新父亲答案时再强制加上一个这个节点的价值以满足依赖性。

DP 时不考虑免费节点的价值,最后统计答案时再处理路径的权值信息会方便很多。多重背包需要单调队列优化。由于我们只关心叶子节点的答案,所以所有更新部分都要在父节点处进行。

卡空间差评。一个神秘的优化是清空 vector 时使用 vector<int>().swap(f[i]) 替代 f[i].clear(),不知道为什么十分有效。

11.15

BK52127 [校模拟赛 Round 38] 关卡设计

枚举最终路径的交点,跑一遍 BFS 和两遍多源 01-BFS 就做完了。然而如果交点是空位的话距离会被算三次,因此喜挂 60pts。

BK52128 [校模拟赛 Round 38] 魔力循环

考虑 \(x!=x(x-1)!\),这启发我们可以从小到大合并,然后就做完了。

BK52129 [校模拟赛 Round 38] 炼金术

赛时一直想质因子只有 \(\log\) 个所以把 \(\gcd\) 拆到因子上之类的总之没有任何道理的东西。首先显然容易想到干掉 \(\mathrm{lcm}\) 得到 \(\frac{a_ib_i}{\gcd(a_i,b_i)}+\frac{a_ib_i}{\gcd(a_i,b_i)^2}\),然后不应该干掉也干不掉 \(\gcd\),正确的思路应该是枚举 \(\gcd\)

具体地,考虑分块,省略散块部分,整块覆盖之后 \(a\) 均相同,我们考虑对每个块预处理出每个 \(a\) 的答案,\(\gcd\) 一定时找最小 \(b\) 即可,放缩一下只要求是因数也行,故而可以先预处理出每个块每个因数存在的最小倍数,然后就枚举因数更新各数答案即可。

视一堆东西同阶复杂度 \(O(n\sqrt n\log n)\)

BK52130 [校模拟赛 Round 38] 风蚀沙丘 / CF1693E Outermost Maximums

不难想到每次选定最大值,然后将其变成当前其两侧的最大值中较小的那个,如果有多个最大值要么操作最左边的要么操作最右边的,直到全变成 \(0\)。这样做显然是对的。

然后其实可以分别处理每个位置值的最优变化序列。利用上述过程不难证明总能将他们合并在一起。

考虑如何快速处理每个位置值的最优变化序列,考虑维护一个值域上的序列,序列各位维护这个数在当前位置左右两侧的出现情况共四种状态,位置移动时只需要单点修改,单次变化可以视作跳到左侧最近的为相应状态的位置,上线段树维护进出区间最小代价即可,询问时区间查一下就做完了。

值得注意的是区间信息需要维护进入节点目标状态与离开节点目标状态组合共四种情况,才可以正确合并,否则可能会有不合法的更优情况。但是大样例全放过去差评。

P3250 [HNOI2016] 网络

正难则反,把路径权值挂在不在路径上的点上即可,树剖一下,给线段树上每个节点开个优先队列标记永久化,\(O(n\log^3n)\) 但跑得挺快。

11.17

AT_agc035_d [AGC035D] Add and Remove

反向做,考虑加入一个数会对答案贡献几次,记其当前左右节点各贡献了 \(x_l,x_r\) 次,则其贡献了 \(x_l+x_r\) 次。于是区间 DP 一下即可。复杂度粗略分析是 \(O(n^22^n)\) 的,但远跑不满。如果记忆化一下精细计算可以做到 \(O(2^n)\) 级别,但我没会。

CF930E Coins Exhibition

存在容斥做法但相对有些复杂。考虑离散化之后顺序 DP,\(f(i),g(i),h(i)\) 分别表示考虑到第 \(i\) 段,这一段全部填 \(1,0\) 或两种都有,易证三者不交。\(h\) 直接计算方案数然后从上一个区间三种求和转过来即可,另外两个需要考虑上一个另一种颜色出现的位置,前缀和一下即可。

AT_agc028_d [AGC028D] Chords

难点在于读题……转化为求每个连通块出现次数。发现放到序列上之后每个连通块都有一个左端点和右端点,满足该区间内所有连边不超出区间边界。于是区间 DP 一下就好了,\(f(i,j)\) 表示 \([i,j]\) 代表了一个连通块的在区间内连边方案数,保证 \(i,j\) 连通,直接保证端点连通不好做,容斥一下用任意配对方案数减去不连通方案数即可。

CF1442E Black, White and Grey Tree

其实二月份做过一次。一开始想的先把一种颜色消完然后另一个挨个消,但这样事实上并不优秀。正确的贪心策略是,当颜色固定时,缩点之后再得到直径,分讨奇偶性整合得到答案为 \(\lfloor\frac{len}{2}\rfloor+1\)\(len\) 为直径长度。当原树是一条链时,这两个策略等价,否则这个策略显然不劣。简单归纳也可以理解不存在更优解。因此 DP 灰点颜色最小化直径即可。

11.18

BK48871 [校模拟赛 Round 39] poker

不难想到建图,然后就是个匹配状物,由霍尔定理加上这题图的性质推一推可以得到,除了树都是合法的。并查集找一下树然后扫描线一下就做完了。

BK48872 [校模拟赛 Round 39] meat

枚举起始点,然后往下搜两层,只搜度数比起始点小的,如果度数相同编号更小,在第二层节点处统计路径信息并更新答案。这样是 \(O(m\sqrt m)\) 的。每个四元环显然只会被统计一次。具体实现上,第一层只搜与处理好的满足偏序的节点,第二层搜所有相邻点判断与起始点的偏序关系。

考虑证明时间复杂度,所有点度数之和为 \(2m\),首先第一层整体复杂度为 \(O(m)\),主要考虑第二层。每个点只会被度数超过他的点搜到,如果当前点度数超过 \(\sqrt m\),那么其只会被搜到不超过 \(\sqrt m\) 次。如果一个点度数不超过 \(\sqrt m\),那么他只会往外搜不超过 \(\sqrt m\) 次。因此复杂度是 \(O(m\sqrt m)\) 的,并且显然跑不满。

P5492 [PKUWC2018] 随机算法

图状压。首先是个 \(O(2^nn^2)\) 的做法,\(f(S,k)\) 表示序列上已经填好了 \(S\) 中的点且最大独立集大小为 \(k\) 的方案数,枚举不在集合中的点直接转移,转移时就固定好其所有尚未固定的相邻点。\(k\) 只跑到最大独立集大小就能卡过去。

然后有个 \(O(2^nn)\) 的做法,\(f(S)\) 表示 \(S\) 为独立集的方案数,枚举新的加入独立集的点转移即可,每次除以一个当前所有可选点的个数表加入概率。

P6622 [省选联考 2020 A/B 卷] 信号传递

看数据范围想到状压,然后发现直接状压是 \(O(2^mm)\) 的,假如我们可以 \(O(1)\) 得到新加入一个点到当前集合产生的贡献的话。直接做空间是 \(O(2^mm)\) 的于是就炸了,考虑卡空间。

方法很多吧。比如说,二进制数由 \(0\) 加到 \(n\) 二进制位只会变化 \(O(n)\) 次,故而可以每次集合变化时更新各个变化的点对其余点贡献产生的影响,贡献数组的空间就只需要 \(O(m)\) 了,总更新时间是 \(O(2^mm)\) 的。

AT_arc105_f [ARC105F] Lights Out on Connected Graph

转化限制,发现奇环就不行,于是相当于要保留一个连通二分图。二分图的话枚举子集作为一侧点即可,考虑连通,直接做不好做,容斥一下,满足二分图性质地任意连边方案数减去不连通方案数即可。经典地枚举最小位所在的独立连通块容易得到不连通的方案数。

11.19

BK52137 [校模拟赛 Round 40] 希巴拉克的道路

不难想到最后方案显然全部在一条边上操作不劣,于是就做完了。随便维护一下凸包即可。

BK52138 [校模拟赛 Round 40] 超纲

一直以为矩阵求逆是超纲算法然后一直想离线扫描线历史信息和如何呢。

手推一下矩阵逆就没了,启发式合并板子。

AT_arc078_d [ARC078F] Mole and Abandoned Mine

刻画一下合法图的状态,不难想到可以视作 \(1\rightarrow n\) 的一条简单路径,每个节点外挂一个联通块,各个节点外挂的联通块互不相交。然后 \(O(3^nn^2)\) 图状压做完了。刷表时动态处理新增联通块的代价可以优化到 \(O(3^nn+2^nn^2)\) 但懒得写了。

CF524E Rooks and Rectangles

奶龙题,满足每一行或者每一列都有车的矩形就可以,两次扫描线维护对应位置最小值即可。

CF1805E There Should Be a Lot of Maximums

奶龙题,\(>2\) 次的必然可以,恰 \(2\) 次的除了两点路径上其他边都可以,直接树剖套线段树给不在路径上的取最大值即可。

11.20

AT_agc059_c [AGC059C] Guessing Permutation for as Long as Possible

不难想到建图,合法当且仅当加入一条边时其一段到另一端已有的所有路径中不存在边均同向的路径。这个东西就很不好做,容斥不了。

事实上归约一下可以得到另一个充要条件,只要加入一条边时不存在第三点 \(c\) 满足两个端点 \(a,b\) 与其组成的路径上 \(a-b\)\(b-c\) 同向即可,容易证明。因此就可以扩展域并查集做一下。

P10197 [USACO24FEB] Minimum Sum of Maximums P

首先有一个 trick 就是 \(\max(a,b)\) 可以表示为 \(\frac{a+b+|a-b|}{2}\)。故而我们只需要最小化 \(\sum\limits_{i=1}^{N-1}|a_i-a_{i+1}|\)

然后考虑 \(K\) 个固定的瓷砖,可以视作他们把原序列分成了若干段。

观察,不难想到各段内部显然是升序或降序填数的。故而总贡献可以视作:

\[\sum |L-mn|+mx-mn+|R-mx| \]

其中 \(L,R\) 为这一段两端固定点的较小值与较大值,\(mn,mx\) 为这一段里填的非定值的最小值与最大值。

继续观察,发现随着 \(mn,mx\) 各自增大,\(|L-mn|-mn\) 不增、\(|R-mx|+mx\) 不降。故而可以得出,每一段填的数不会有相交关系,要么不交要么包含,且小段的值域区间内不会有数给包含它的大段。

于是考虑区间 DP,发现段数很小可以状压,于是 \(f(l,r,S)\) 表示使用值域上 \([l,r]\) 的数填满了 \(S\) 中的区间的最小代价。转移只有三种(\(\gets\) 表示取较小值操作):

  • 在一侧预留一个数给包含它的区间,\(f(l,r,S)\gets \min(f(l+1,r,S),f(l,r-1,S))\)
  • 把两段拼接起来,\(f(l,r,S\cup T)\gets\min f(l,k,S)+f(k+1,r,T)\)
  • 在外面套一个区间,要求 \(sz_x= r-l+1-sz_S\)\(f(l,r,S\cup\{x\})\gets f(l+1,r-1,S)+|L_x-l|+r-l+|R_x-r|\)

细节上,给区间最两侧额外加两个 \(10^6\) 的定点以方便 DP,最后减去贡献即可。

P5982 [PA 2019] Trzy kule

有点神秘,首先单步容斥转化为求三个都不满足的数量,考虑每一位对三个串的贡献搭配共 \(8\) 种,将其中各位完全相反的两两配对,那么每一种配对中知道一侧的数量就可以知道另一侧的数量,故而得到了一个 \(O(n^4)\) 做法。折半搜索,推一下式子发现是一个二维前缀和形式,于是就 \(O(n^2)\) 解决了。

AT_agc043_d [AGC043D] Merge Triplets

难点在于转化,如果按前缀最大值所在位置分段,那么所有段长度不超过 \(3\),且长度为 \(2\) 的段数不超过长度为 \(1\) 的段数。我不知道如何理性地快速推出这个结论,哭哭。

有这个就可以 DP 了,\(f(i,j)\) 表示当前往序列里填了 \(i\) 个数,长度为 \(1\) 的段数减长度为 \(2\) 的段数为 \(j\),只考虑填入的数的相对大小关系的方案数,转移就考虑新加入一个长度为一或二或三的段即可,是简单的。

CF1044D Deduction Queries

奶龙题,区间异或等价转化为前缀和的两个点异或,由于异或操作很好的性质直接带权并查集一下,能判断区间和当且仅当前缀和对应端点在同一连通块,直接查到根的异或和异或一下即可。

11.21

BK52122 [OIFHA2025 R8] 神秘埃及

怎么打 OIFHA 的题。不难发现一次一操作能减少零的数量当且仅当其在一个至少三个端点为零的矩形上进行。归纳得到,只要当前同时存在一行和一列零的个数不少于二,就能经过不超过两次操作减少零的数量。那么,只要不满足上述条件了,当前剩下的零的数量就是答案。

一个做法是利用 \(2\times2\) 的矩阵把所有零压到最后一行和最后一列,然后一一匹配把能配对的压到对角线上即可。

BK52123 [OIFHA2025 R8] 海盗港湾

神秘题。观察发现,我们首先将原图排上整齐的井字状白点,满足上下、左右相邻的节点间距均为 \(b\) 并且再塞不下更多的白点。首先这样是肯定满足的,在此基础上,我们可以选择一些行左右挪动,或者选择一些列上下挪动,只要仍然满足填不下更多白点,就是合法的。两种情况分别算一下即可,容斥掉被算重的仍是整齐井字状的状态。

BK52124 [OIFHA2025 R8] 狂野西部

首先为了方便,我们将之转化为网格图,然后就是求 \((1,1)\rightarrow(n,n)\) 的路径颜色方案数。这个图的特点是,每一行及每一列内的边颜色均相同,后文钦定第 \(i\) 行颜色为 \(a_i\),第 \(j\) 列颜色为 \(b_j\)

定义 \(f(i,j)\)\((1,1)\rightarrow(i,j)\) 的路径颜色方案数,有转移 \(f(i,j)\gets f(i-1,j)+f(i,j-1)-X\),考虑算重的部分即 \(X\)

首先会算重仅当 \(a_i=b_j\),然后会发现,两条路径重复的必要条件是从一个 \((i-k,j-k)\) 满足 \(a_{i-k}=b_{j-k}\) 的点开始分叉,在这里一个向上走一个向右走,然后二者一直走镜像路径到 \((i,j)\)

我们考虑求出 \((i-k,j-k)\rightarrow(i,j)\) 的镜像路径对数,这显然只与所有满足 \(0\le l\le k\land a_{i-l}=b_{i-l}\) 的点有关,一条只在这些行列上经过的路径才有镜像路径。同时,假如这条路径经过了 \((i-l,j-l)\),他会在 \((i-l,j-l)\) 被去重,因此在 \((i-k,j-k)\) 去重的路径不应经过之后的满足 \(a_{i-l}=b_{j-l}\) 的点。故而,记满足条件的 \(l\)\(z\) 个,镜像路径对数即为 \(C_{z-1}\)\(C\) 为卡特兰数。

于是就得到了完整转移式:

\[f(i,j)\gets f(i-1,j)+f(i,j-1)-[a_i=b_j]\sum_{k=1}^{\min(i,j)-1}[a_{i-k}=b_{j-k}]f(i-k,j-k)C_{z-1} \]

\(a_i=b_j\)\((i,j)\) 只有 \(n\) 个,故而每次直接枚举 \(k\) 转移即可。最后复杂度 \(O(n^2)\)

BK52125 [OIFHA2025 R8] 巨浪沙滩

难点在于克服公式恐惧症看懂题目在狗叫什么。建后缀树然后启发式合并即可。

11.22

BK52140 [校模拟赛 Round 42] 千万道伤痕

不难想到可以将操作变为任意选择两个点 \(x,y\),将其权值变为 \(w_y+\Delta h\)\(w_x-\Delta h\)。我们拆掉 \(\Delta h\),可以得到交换之后的总贡献:

\[|w_y+h_y-v_x-h_x|+|w_x+h_x-v_y-h_y| \]

于是就可以视作将所有 \(w+h\)\(v+h\) 一一匹配,贪心,各自排序直接算贡献即可。

BK52142 [校模拟赛 Round 42] 星之卡比

怎么是根号分治。

首先考虑长度不超过 \(\sqrt n\) 的串间。考虑一个位置关系一致的共同点对,各自串中左侧的点的后一位也需要相同。因此我们记 \(f(i,j)\) 表示 \(i\)\(j\) 组成点对时,\(i\) 的后一位应当是多少。没有冲突显然就是合法的充要条件。每个串暴力枚举点对即可。

然后考虑长度超过 \(\sqrt n\) 的串,直接枚举第二个与其匹配的串,先找到一个串中最靠后的共同点,然后往前枚举即可,各个共同点只要在两个串中后一位相同即可。假如后一位不是共同点,那么显然匹配不上。否则,不合法情况会在后一位判。因此这样判断也是充要的。

复杂度 \(O(n\sqrt n)\)

BK52143 [校模拟赛 Round 42] 潮水啊,我已归来

怎么还有原批环节。放一道奶龙题当 T4 然后写最长的题解就糊弄过去了是这样的。

很典的 trick 是前缀 \(\gcd\) 只有 \(\log V\) 种。故而可以枚举 \(i\) 然后一段一段地处理 \(j\)

考虑左边一坨的答案怎么求,首先不难发现这个异或只与最后三十位有关,因此把结果的最后三十位额外提出来处理。考虑 \(\sum_{i=0}^v x\oplus i\) 怎么求,逐位处理,考虑第 \(w\) 位为 \(1\) 的次数是可求的,不难发现是一个循环节是 \(2^{w+1}\) 的循环状物。

然后就做完了。

11.24

QOJ9904 最小生成树

倍增并查集板子。

P7307 [COCI 2018/2019 #1] Teoretičar

要求颜色数不超过二的整数次方,考虑分治。

对于当前的边集,考虑每次将其分成两份,使得每个节点的度数减少一半。当当前边集下所有点度数不超过 \(1\) 的情况下直接把当前边集所有边染成一个颜色即可。

如何实现呢,考虑每次找欧拉回路给边定向,按方向分作两个边集。为了保证欧拉回路也就是每个点度数均为偶数,新开两个虚点即可,由于欧拉回路中每个点都是一进一出,因此这么分所有点度数就减半了。

具体实现上得实现地精细一些,比如遍历的点集只能是与当前边集有关的,如果每次都遍历所有点就炸了。复杂度为 \(O(m\log m)\)

AT_joi2014ho4 フクロモモンガ (Sugar Glider)

首先我们不难发现,最优路径必然可以分为前后两部分,前一部分只往下爬,后一部分只往上爬。更具体地,后一部分每次都只会往上爬到恰好可以飞到下一个地方的高度。

只考虑第二部分的话(实际上,忽略首次进入第二部分的那个点),相当于每条边边权都是一定的,故而可以直接跑最短路求出答案。

在第一部分中,我们只会向下爬,并且不会停歇,因此在这一部分,一个时间唯一对应了一个高度。事实上,我们到达一个点的初始高度越高,到达时间越早,显然是不劣的。因此,这部分也是直接跑最短路即可正确处理。

那么就可以整合两个部分,直接跑最短路即可。

CF1361E James and the Chase

不难想到如何判定一个点是不是好点,只要以其为根的 DFS 树上只有树上边和返祖边即可。

但这么判还是太慢了。事实上,当找出一个好点以及相应 DFS 树时,就已经可以找到所有好点了。有结论,除了根节点外,一个点为好点当且仅当其子树中有且仅有一条返祖边指向其祖先,且指向的祖先为好点。这是因为当前已经没有前向边与兄弟边了,故而每个点只需要考虑到其父亲的路径方案数。证明是显然的。树上差分存返祖边数,然后再对每个点记一下可以走到的最浅的祖先即可。

这要求我们找到一个好点,由于题目规定好点数量应超过 \(20\%\),故而直接随一百个试就行。

P7298 [USACO21JAN] Dance Mooves G

不难想到按 \(k\) 次分段处理,每个点向段后所在位置连边,会形成若干个环,独立处理每个环即可。如果覆盖完了是简单的,否则环内每个点都是等长的一段,双指针即可。每条边存经过的所有位置,总量是 \(O(n+k)\) 的,故而可以暴力改。预处理出每个点最后散段经过的点集即可,总量同上,然后双指针过程中存答案时把相应的点集合并一下即可。

11.25

BK52158 [校模拟赛 Round 43] 平衡

不难想到每个颜色染的边必然在一个连通块否则必然不优。先二分一下答案,于是可以处理每个点子树内至少要有几条边与父边相同。考虑怎么处理这个,首先得到所有子节点各自要几条边,然后用新一种颜色满足尽可能多的需求,剩下的再交给父节点。一个子节点内只能全部满足或者全不满足,直接 01 背包一下即可。最后判一下根节点的需求能否满足即可。

BK52156 [校模拟赛 Round 43] 网络延迟

正着去生成这棵树很不好想,反正我想不出来。考虑正难则反,对于给定的一个合法树结构,怎么把他缩回根节点?不难发现,只要每次选定一对兄弟叶子节点把他们删除即可。这对节点必然满足值相差不超过一,而他们的父节点值就是他们的最小值,故而也可以视作是删除了较大的那个点。

因此我们可以每次选定序列中一对相邻点满足值相差不超过一,然后删除较大点,如果能删到只剩最后一个 \(0\) 就是合法的。贪心的,每次尝试去删除当前序列的最大值即可。

CF1801D The way home

不难想到,对于一条路径,表演操作必然形如,在路径上 \(w\) 各个前缀最大值处进行若干次使得恰好可以到达下一个前缀最大值处。这么贪心显然是不劣的。

然后就不知道怎么做了。观察数据范围,发现 \(n\le 800\),于是考虑暴力。直接拆点,把每个位置的每种可能的前缀 \(w\) 最大值状态都拆出来,形成 \(O(n^2)\) 个点,然后跑最短路即可。

还有一个问题,就是我们貌似要同时在意当前的表演次数与剩余钱数,然而事实上只需要在保证表演次数最小的前提下最大化剩余钱数即可。由于我们的贪心策略是只在前缀最大值上操作恰需要的次数,因此操作更多的方案,既然操作过了,其剩余钱数必然不超过上一步的前缀最大值,故而操作更少的方案在当前前缀最大值处额外操作一次就能得到比那种方案更多的剩余钱数。

AT_cf17_final_j Tree MST

今年二月份做的,今天只是重新口胡了一遍,太懒了导致的。

最小生成树,首先考虑 Kruskal,然后发现不可做其实也可做。考虑 Boruvka,发现每次对每个点找到最小的边是简单的,换根 DP 维护最小值和颜色不同的次小值即可。于是就做完了。

由于本题 Kruskal 做法可以积累一个 Trick 所以还是记录一下,就是对于一个图,可以先选若干个边集满足并起来是全集,然后对每个边集分别求 MST,最后把每个边集的 MST 并起来求 MST 就是答案,可以简单反证。对于这道题,就是点分治一下产生 \(n\log n\) 条边跑一遍 Kruskal 即可。但这么做比 Boruvka 做法多一个 \(\log\)

QOJ8056 Travel 2

神秘题啊。

首先那个 \(2m\) 是好想的,就是每条边都只从两侧被遍历一次,就是一个搜索。但是暴力回溯显然会炸掉,考虑如何保证除此之外只有 \(2n\) 次额外的查询。

考虑如下搜索方案:如果当前点仍有边没有走,就走过去。否则,与当前点相连的所有边必然在两个方向上都走过了,想象一下,就是因为你显然搜过一条路径之后将会反向搜回来。

那么,在这种情况下,我们就固定住该点,并走向所有与其连边的尚未被固定的点,这些点回溯之时必然已经被固定了,所以可以直接一步走回。这些步骤走的边最后会形成一个树形结构,故而会额外走 \(2(n-1)\) 步,符合条件。容易证明最后所有点都会被固定,且所有边均被搜索过。

11.26

BK52166 [校模拟赛 Round 45] 王哥与演出 / AT_jsc2019_qual_e Card Collector

首先这类网格问题考虑经典地转化为二分图,考虑现在变成了一个什么问题,每个点都可以选一条临边并得到边权,每条边只能被选一次。那么选出来之后必然形如基环树森林,同时任一生成基环树森林也都可以找到相应方案。故而直接贪心地找最大权基环树森林即可,类似于 Kruskal 算法,按边权降序能加边就加边,容易反证法证明正确性。

BK52165 [校模拟赛 Round 45] 王哥与荷塘

首先考虑静态全局信息怎么维护,直接硬做显然没有前途。考虑拆掉绝对值,由于我们要最大值,因此不合法不优,直接四种情况取最大值即可。修改的话考虑放到线段树上维护,上传是简单的,整块修改的话块内答案不变,四种最大值信息轮换一下即可。

11.27

CF285E Positions in Permutations

恰好,考虑容斥。考虑钦定 \(k\) 个点为好位置的方案数,考虑 DP,因为只关心 \(|p(i)-i|=1\) 的位置,也就是只考虑相邻两位,因此考虑 DP 状态 \(f(i,j,0/1,0/1)\) 表示前 \(i\) 个有 \(j\) 个好位置,\(i\) 处是否被选填,\(i+1\) 处是否被选填的方案数。就这样吧。

P10241 [THUSC 2021] 白兰地厅的西瓜

没写,口胡的。考虑淀粉质,没了。\(O(n\log^2n)\)

11.28 写了长剖做法,考虑换维,然后长剖,序列具有单调性每次加入点单次二分即可,没了。\(O(n\log n)\)

11.28

CF1889C1 Doremy's Drying Plan (Easy Version)

发现有用的只有被覆盖不超过两次的点。两个区间不相交的情况直接选最大的两个即可,考虑两个区间相交,那么每个二次点只会给一对区间贡献,直接枚举即可。

11.29

P14635 [NOIP2025] 糖果店 / candy

发现最后一定形如各个数选偶数个,然后再选一些数选一个。

前一部分,只用找 \(x+y\) 最小的一直选就行了,后一部分,排序一下跑一遍就行。

P14636 [NOIP2025] 清仓甩卖 / sale

可能场切了吧……就当我场切了吧。

手摸一下,发现不合法的充要条件为,存在一个 \(w=2\) 的数 \(x\),选到他之前的时候恰好花费了 \(m-1\),并且在其之前有一个 \(w=1\) 的数价值为 \(y<x\),在其之后还有一个 \(w=1\) 的数价值小于 \(x-y\) 或者在其之后全都是 \(w=2\) 的。

考虑枚举这个 \(x\),然后想如何让其之前恰好花费 \(m-1\),不难想到,原来就先于他的数操作后仍然先于其操作,并且会使消耗加一;原来不先于他但是先于 \(\frac{x}{2}\) 的数,操作后会使消耗减一。因此相当于两部分选出来的数差一个值,范德蒙德卷积一下就可以 \(O(1)\) 计算。然后再考虑在 \(\frac{x}{2}\) 后面的部分,不妨枚举首个 \(w=1\) 的位置,那么其之后状态一定,其之前任意,方案数是简单的;再预处理一部分东西就可以做到严格 \(O(n^2)\) 了。

结束了……


再见,这流光溢彩的冬月。

posted @ 2025-11-03 18:27  LastKismet  阅读(23)  评论(0)    收藏  举报