5 月做题记录
广东省集 Day11
T1
考虑询问本质上能获得什么信息,发现当你询问 \(p\) 后,交互库会告诉你假币的 \(p\) 值为多少。
考虑什么时候 \(W=1\),发现必然是存在方案使得 \(p_i \leq a_i\) 且 \(p_i\) 互不相等,这等价于对于所有 \(i\) 都有 \(a_i \geq i\)。
然后考虑最优方案会是怎么样,大概是可以贪心,按照 \(a\) 排序后维护假币候选集合 \(S\),每次从前往后遍历 \(S\) 并为其选定 \(p\) 值,对于 \(S\) 中的一个数 \(a_i\),令其 \(p\) 为 \(j \leq a_i\) 且 \(cnt_j\) 最小的 \(j\),然后 \(cnt_j \gets cnt_j+1\) 即可。
T2
等价于计算从 \((x',y')\) 出发有多少长度为 \(t'\) 的四联通路径且第 \(t'-t\) 次经过的位置不是 \((x,y)\)。
用总路径数量减去 \((x',y')\) 到 \((x,y)\) 长度为 \(t'-t\) 的数量乘以 \((x,y)\) 出发随意走 \(t\) 步的数量即可。
这个是反射容斥板子。
首先,从 \((0,0)\) 走到 \((n,m)\),每次只能向右或向上,要求不经过 \(y=x+l\) 与 \(y=x+r\),满足 \(l<0<r\),的方案数为 \(\sum \limits_{k \in \mathbb{Z}} \dbinom{n+m}{n-k(r-l)} - \dbinom{n+m}{n-k(r-l)+r}\),原因是你考虑用总方案减去第一次经过的是 \(y=x+r\) 的方案数,或者第一次经过的是 \(y=x+l\) 的方案数,但是应该减去先经过 \(l\) 再经过 \(r\) 或者先经过 \(r\) 再经过 \(l\) 的,等等,最终得到这样的一个式子。
对于这个题,首先把行列拆开,然后卷积在一起就行,因为这个题只要求单点的值所以不需要 NTT。但是终点 \((n,m)\) 并不确定,需要对于范围内的所有 \(n+m\) 计算对应的所有 \((n,m)\) 的结果的和,这个可以考虑总方案数是 \(2^{n+m}\),减去和 \(y=x+l\) 或 \(y=x+r\) 的方案数,也就是对于某个 \((x,x+l)\) 求 \((0,0)\) 到 \((x,x+l)\) 且之前没有经过边界的方案数,\((x,x+r)\) 同理。那么有 \(f_i = 2^i-\sum \limits_{1 \leq j < i} g_j2^{i-j}\),直接计算即可。
这样做复杂度是 \(O(\dfrac{t'^2}{n})\) 的,因为要做 \(O(t')\) 次反射容斥,不难注意到这个过程也可以直接 DP,记 \(f_{i,j}\) 表示走了 \(i\) 步到了 \(j\) 的方案数,复杂度 \(O(t'n)\),对 \(n\) 根号分治即可做到 \(O(t'\sqrt {t'})\),可以通过。
T3
考虑把所有 \(l,r,x,y\) 离散化,对于相同的值,视为左端点更小右端点更大,这样所有区间端点两两不同且不影响答案。
对于一个离散化后的区间序列,我们构建一个匹配括号串,对于每个区间 \([l_i,r_i]\),将 \(s_{l_i}\) 设为 \(\texttt{(}\),\(s_{r_i}\) 设为 \(\texttt{)}\),我们声称其宽度为序列中相邻的 \(\texttt{()}\) 数量。首先这个数量容易取到,对相邻的 \(\texttt{()}\) 编号,每个区间 \([l_i,r_i]\) 的映射取其包含的编号区间即可,很显然原来不交的映射后仍然不交,原来有交的映射后必然在交集中存在相邻 \(\texttt{()}\),这是因为交集开头是 \(\texttt{(}\) 且结尾是 \(\texttt{)}\)。另一方面,需要证明至少需要这么多个数做映射,对于每个相邻的 \(\texttt{()}\),取出所有包含它的区间在映射后的交集中的任意一个数,容易发现任意两个相邻 \(\texttt{()}\) 的这个交集中任意数都不同,所以至少有这么多个数。
注意到一个非空合法括号串的相邻 \(\texttt{()}\) 数量等于相邻 \(\texttt{)(}\) 数量加 \(1\)。考虑将原问题改为有 \(x\) 个区间,每个都可以选或不选共 \(2^x\) 种方案,求宽度的期望值。根据期望的线性性对任意两个 \(\texttt{)(}\) 计算概率求和即可。概率为 \(2^{c+2}\),其中 \(c\) 为这个 \(\texttt{)}\) 和 \(\texttt{(}\) 之间所有括号对应的不同区间数量。
考虑原题的询问,是保留每个区间和 \([x,y]\) 相交的部分,但是不难发现如果一个区间不包含于 \([x,y]\),则要么右端点变为 \(r\),要么左端点变为 \(l\),对应括号来说,就是在 \(y\) 处加一个右括号或者在 \(x\) 处加一个左括号,但是由于我们只需要计算 \(\texttt{)(}\) 的贡献,所以在 \(y\) 处的右括号不可能产生贡献,\(x\) 处左括号同理,所以问题等价于只保留 \([x,y]\) 内的括号计算答案。
考虑从前为往后扫描线,对于每个 \(s_i = \texttt{(}\) 维护其前面所有 \(\texttt{)}\) 对应的这一段的 \(2^{c+2}\) 的结果,发现只需要维护单点修改区间乘以 \(2\) 的逆元,以及查询区间历史和,直接线段树维护矩阵即可。发现矩阵是 \(2 \times 2\) 的上三角矩阵,手动展开矩阵操作即可降低常数。复杂度 \(O((n+q) \log n)\)。
CF1644F
如果只有操作二怎么做,发现两个序列可以互相转化等价于离散化后结果相同。于是枚举序列有多少种不同的数,答案为 \(\sum \limits_{i=1}^{\min(n,k)} \begin{Bmatrix} n \\ i\end{Bmatrix}\)。
考虑操作一,对于每个序列,将所有相邻相同构成的连续段拉出来,将最后一段删去,如果之前的所有段长度的 \(\gcd > 1\),则可以等比缩小为另一个序列,所以我们只需要计算除去最后一段后所有长度 \(\gcd=1\) 的方案数。
枚举 \(d\) 表示前面所有段的都是 \(d\) 的倍数,则得到 \(\lceil \dfrac{n}{d} \rceil\) 个段,则要求等价于每一段内的数都相同,那么直接用之前的式子计算既可求出这个答案,最后容斥回去即可得到答案。
因为要计算同行第二类斯特林数,需要用 NTT。复杂度为 \(O(\sum \limits_{i=1}^n \lceil \dfrac{n}{i} \rceil \log \lceil \dfrac{n}{i} \rceil) = O(n \log^2 n)\)。
P5327
有一个显然的 polylog 做法,树剖将一条路径变成 \(O(\log n)\) 个区间,然后做 \(O(n \log^2 n)\) 个区间覆盖 \(1\),查全局非 \(0\) 数量,扫描线维护就是 \(O(n\log^3 n)\) 的。
这个做法前途不好,考虑对于一个点 \(u\) 求有多少 \(v\) 符合条件。这个等于所有经过 \(u\) 的给定路径 \((x,y)\) 构成的所有 \(x,y\) 构成的虚树的边集大小,经典结论按照 DFN 序求环上两两距离和即可。这个东西很容易用线段树合并维护,复杂度 \(O(n \log n)\)。
P12399
如果初始序列全非正或非负,容易求出答案。
否则,考虑找到一个 \(x\) 使得将 \(a_x\) 乘以 \(-1\) 后最大子段和变大,则目前序列的所有最大子段和都必然包含 \(x\),否则乘 \(-1\) 前最大子段和会更大。
考虑从 \(a_x\) 开始分别往左右将每个数变为非正数,依次枚举每个数,将其乘以 \(-1\),若最大子段和发生变化容易判定这个数的正负号,否则其必然在某个最大子段的左右端点旁边,则这个数必然为 \(0\)。做完了。
P7126
连通块数经常考虑点边容斥,但是每个连通块不一定是树所以毫无道理。
考虑对每个连通块钦定代表元,具体地,任意指定根,对于每个连通块钦定其代表元为连通块中 BFS 序最小的点。我们声称对于连通块中任意一个非代表元 \(i\),存在 \(j\) 使得 \(j\) 的 BFS 序小于 \(i\) 的 BFS 序且 \(dis(i,j) \leq d\),证明考虑只需要证对于 \(b_i < b_j < b_k\),其中 \(b\) 为 BFS 序,若满足 \(dis(j,k) \leq d\) 且 \(dis(i,k) \leq d\) 则有 \(dis(i,j) \leq d\),这个可以通过简单分类讨论 LCA 即可证明。
对于原题,考虑每个 \(x\) 什么时候会成为代表元,这等价于不存在 \(y \in [l,r]\) 使得 \(b_y < b_x\) 且 \(dis(x,y) \leq d\)。对每个 \(x\) 求出 \(<x\) 的最大的 \(y\) 与大于 \(x\) 的最小 \(y\) 即可将问题转成二维数点。求这个的过程可以简单点分治维护。复杂度 \(O(n \log^2 n + q \log n)\)。
P5311
对于询问点 \(x\),如果能找到一个 \(y\) 使得 \(x,y\) 在 \(l,r\) 意义下连通,则答案等于询问 \(y\) 的答案。
考虑在点分树上找到最浅的 \(x\) 的祖先 \(y\) 使得 \(x\) 与 \(y\) 连通,则我们声称与 \(x\) 连通的点必然都在 \(y\) 子树内,这是因为点分树上两点在原树上的路径经过点分树上两点的 LCA,于是问题转化为子树内的查询。对每个子树做一次扫描线就行了。复杂度 \(O(n \log^2 n + q \log n)\)。
P6782
显然问题瓶颈在于点 \(u\) 的儿子个数可能过大。
考虑类似根号分治,对于点 \(u\) 的子树大小大于 \(\sqrt n\) 的儿子,暴力做。则我们要求 \(O(n\sqrt n)\) 次区间小于某数个数,扫描线的时候分块即可。
对于点 \(u\) 的子树大小不超过 \(\sqrt n\) 的儿子,将其子树内两两点 \((u,v)\) 加入集合 \(S\)。对集合 \(S\) 内的任意一个二元对 \((u,v)\) 求出 LCA,那么询问相当于求点 \(u\) 对应集合内有多少 \((u,v)\) 满足 \(l \leq u < v \leq r\),同样的扫描线时分块即可。
现在只需要分析 \(|S|\) 的量级。考虑一个点 \(u\),有多少 \(v\) 会使得 \((u,v) \in S\),显然只有 \(O(\sqrt n)\) 个 \(v\),所以总复杂度 \(O(n \sqrt n)\)。
CF343E
建出最小割树,相当于是给你一棵树,每条边有边权,构造排列 \(p\) 最大化 \(\sum \limits_{i=1}^{n-1} d(p_i,p_{i+1})\),\(d(u,v)\) 表示 \(u\) 到 \(v\) 路径边权最小值。
我们声称答案为每条边边权和,考虑证明与构造。
上界的证明很显然,因为每条边至少被经过一次,所以答案不超过每条边边权和。
考虑构造,每次将目前连通块的边权最小的边拉出来,删掉递归两侧,然后将两侧的拼起来,显然每条边作为最小值恰好一次。
AGC064D
考虑如何判定一个字符串可以被生成。考虑原字符串从右到左的每一个 B 以及其左边跟着的若干个 R,则要求最后一个 B 跟着的 R 只能在最终序列的开头的连续 R 段内,倒数第二个 B 跟着的 R 要么在序列开头,要么在这个 B 右侧接着的连续 R 段内,以此类推。
发现判定一个字符串合法等价于初始长度为这个字符串开头的 R 数量,依次枚举原字符串从后往前的每一个 B,假设其前面跟着 \(x\) 个 R,则长度减去 \(x\),然后长度加上这个字符串中目前最大的没被选过的极长 R 段的长度。要求任意时刻值非负。这个可以简单 DP,按照极长 R 段长度从大到小枚举,复杂度 \(O(n^3 \ln n)\)。
CF526G
考虑另一个问题,给定一棵有根非负权树和 \(k\),求至多 \(k\) 条根到叶子的路径的并的权值和最大值。这个是经典结论,长链剖分后取前 \(k\) 大的和即为答案,证明比较显然。
考虑现在问题有两点不同,第一是取的路径一端不要求是根,另一个是给定 \(x\),要求 \(x\) 必须被路径的并包含。忽略 \(x\) 的限制,考虑前者怎么做。
取出树的任意一条直径,我们声称存在最优方案使得这条直径的至少一个端点被覆盖。这个是容易反证的,因为如果直径两端都未被覆盖可以直接调整获得一个不劣的方案。
于是我们以直径两端分别为根各做一次取最大值即可。
考虑现在根确定后怎么做。我们必然是选择 \(2k\) 个叶子,有一个事实是一棵树如果有 \(2x\) 个叶子,可以用 \(x\) 条路径覆盖所有边,原因是你找到带权重心后把子树两两匹配即可。
于是如果忽略连通块包含 \(x\) 的限制,容易知道答案应该是前 \(2k-1\) 条长链权值和,减 \(1\) 的原因是已经选了根这个叶子了。
加入路径包含 \(x\) 的限制,有两种可能的调整方式,一种是将第 \(2k-1\) 条长链删去,加入 \(x\) 往上的那条,第二种是把 \(x\) 向上的那条调整到 \(x\) 这边。这都是容易倍增维护的。
5.5 模拟赛
T1
考虑判定一个子序列合法,容易发现可以转化成执行若干次区间加,要求的是全局最大值不超过 \(m\)。
进一步你要求选一个最优的符合条件的子序列,这个可以转为一个经典模型,叫做你有若干区间,每个区间有个权值,你要选若干区间使得不存在某个位置被所有区间覆盖超过 \(m\) 次,最大化选的区间的权值和。
这个等价于选 \(m\) 次,每次选出若干的之前没有使用过的不交区间,充分性显然,必要性可以归纳证明,大概是你每次贪心地从前往后选区间即可。
这个模型就可以直接费用流了,注意到原图是 DAG 所以直接原始对偶即可做到 \(O(mn \log n)\),但是我还不会原始对偶,哈哈哈。
T2
一眼就有 polylog 做法是,线段树分治,然后李超维护一下,但毫无前途。
考虑为什么你需要李超树,因为你加入的是线段而不是直线。以 \(x_0 > x_i\) 为例,这个式子是 \(\dfrac{w_i}{x_0 - x_i}\),显然要取倒数,即求 \(\dfrac{x_0-x_i}{w_i}\) 的最小值,即 \(\dfrac{x_0}{w_i} - val_i\) 的最小值。为什么不能直接加入直线,原因是要求的是最小值,但是 \(x_0 < x_i\) 时式子是负数,全错了。
但是你可以视作你只是把 \(y = \dfrac{1}{w_i}x - val_i\) 在 \(y \leq 0\) 的部分删掉,那么这个式子写成凸包的形式应该是 \((-val_i,-\dfrac{1}{w_i})\),询问要求的是截距最小非负值,然后把这个取反就是 \((val_i,\dfrac{1}{w_i})\),要求截距最大非正值。不妨假设点都在第一象限且询问斜率为正,那么其实要求的是点到原点连线的斜率小于等于给定斜率下的这些点的最优值。考虑离线按照斜率排序依次加入,那么原题的限制还要求那个点是在询问时没有被删去,这个直接在线段树上维护这个凸包就行了。由于加入和查询斜率都是单增的所以容易用单调栈做到均摊 \(O(1)\)。所以总复杂度 \(O(n \log n)\)。
T3
不会多项式。
无来源的题
记点 \(i\) 二级邻域为 \(S_i\)。
考虑随便确定一个根,假设叫做 \(r\)。
考虑一层层确定每个点。
对于点 \(r\),只要能找到 \(r\) 的所有儿子,那么可以确定 \(dep=2\) 的点的集合,记为 \(T\),而对于 \(r\) 的每一个儿子 \(i\) 直接将 \(S_i\) 与 \(T\) 求交即可得到 \(i\) 的所有儿子,从而可以确定 \(dep = 3\) 的点,以此类推。
所以如果 \(r\) 的儿子确定,可以在 \(O(\dfrac{n^2}{w})\) 的复杂度内还原一棵树。
对于判定一棵树是否合法,可以维护每个点二级邻域的哈希,这个是简单的。
现在问题在于确定 \(r\) 的每个儿子。
显然问题不一定有唯一解,所以不可能唯一确定所有儿子。
所以要聪明一点。如果 \(r\) 是叶子,那么有唯一儿子,所以直接枚举儿子是谁就能做到 \(O(\dfrac{n^3}{w})\)。
考虑什么样的点会是叶子。
首先,对于叶子 \(i\),存在 \(j\) 使得 \(S_i \subseteq S_j\),显然取 \(j\) 为 \(i\) 的唯一邻点即可。
然后考虑对于 \((i,j)\),\(i\) 不一定是叶子,什么情况下有 \(S_i \subseteq S_j\)。
首先要满足 \(dis(i,j) \leq 2\),\(dis(i,j)=2\) 时可能符合条件当且仅当 \(i,j\) 同时为叶子。
我们声称取 \(i\) 为 \(|S_i|\) 最小的满足存在 \(j\neq i\) 使得 \(S_i \subseteq S_j\) 的 \(i\)。
考虑为什么这是对的。对于 \(i\),存在 \(j \neq i\) 且 \(S_i \subseteq S_j\) 且 \(i\) 不为叶子,只有可能是 \(dis(i,j)=1\),且 \(S_i = S_j = \{1,2,3,\cdots,n\}\),除了菊花,必然存在叶子 \(x\) 使得 \(|S_x| < n\)。
除了菊花,都能保证找到的 \(i\) 为叶子,菊花只有一个点不是叶子,最多多做一次就行。
CCPC 2021 Harbin
A. So Many Lucky Strings
考虑将每一种选择子序列的方式刻画成一个唯一的操作序列,从对称中心开始,每次要么选择左边的字符串,要么选择右边的字符串。要求任意时刻左右两侧多出的字符串不超过其对应的那部分长度。然后可以直接进行 DP,记 \(f_{i,j,l}\) 表示目前最左侧选了 \(s_l\),最右侧选了 \(s_r\),且右侧多出了 \(l\) 个,\(l\) 可能是负数。根据上述过程可知 \(l \geq 0\) 时有 \(l \leq |s_j|\),\(l < 0\) 时有 \(|l| \leq |s_i|\),所以总状态数是 \(O(n \sum |s_i|)\) 的,转移根据 \(l\) 的符号决策往左右多选某一个,直接转移是 \(O(n^2 \sum |s_i|)\),可能需要前缀和优化一下。
C. Colorful Tree
记 \(f_{i,j}\) 表示子树 \(i\) 内,初始全都被染成颜色 \(j\),最小操作次数。很容易线段树合并做到 \(O(n \log n)\)。
L. Karshilov's Matching Problem
建立 AC 自动机,求原串每个前缀的答案是很容易的。对于 AC 自动机上每个点处理出从其开始走 \(2^k\) 步某个数到达的点以及贡献的答案。
类似颜色均摊段,把所有涉及到修改的后缀写成若干连续段的形式,并且在每个连续段末尾维护前缀答案以及到达节点。修改直接均摊连续段维护即可。
5.6 模拟赛
T1
显然有一个 \(O(n^2)\) DP,\(f_u\) 表示只在 \(u\) 子树内选若干条路径的最大权值和,转移枚举某条以 \(u\) 为 LCA 的路径被选,然后路径把子树拆成了若干棵小子树,转移是简单的。
这个东西很容易用数据结构优化,只需要维护单点修改路径求和,复杂度 \(O(n \log n)\)。
T2
原题:CF1740G。
注意到了就做完了。
猜测最优方案可以使得每个格子都被保留,考虑怎么构造。
发现你的行走过程中,每个点会被贡献到当且仅当其为前缀最大值。
容易发现原网格中值最小的位置必然只能被第一次就射入到这个格子的光线贡献到,所以其答案必然为 \(0\)。
然后依次考虑第二小,第三小,等等,发现对于每个格子,对这个格子有贡献的光线只能经过之前处理过的格子,所以很容易维护出每个格子四个方向进来的数量与权值和,用个并查集维护即可做到 \(O(nm \log nm)\)。
T3
不是很懂。
CF2107F2
考虑刻画整个过程的最优策略。
找出全局最靠左最小值 \(a_x\),则我们知道从后往前到 \(x\) 时花费必然为 \(a_x\),且到了 \(x\) 之后会不断和前面交换。但是最优策略可能会先将 \(a_x\) 与某个 \(a_y\) 交换,然后从 \(y\) 开始不断往前交换。对于每个后缀,找到最靠左最小值为之后枚举其与谁交换,问题变为一个更小的后缀,DP 即可做到 \(O(n^2)\),可以通过 F1。
进一步,我们声称要么 \(a_x\) 不与任何数交换,要么与 \(a_n\) 交换,原因是考虑其若和 \(a_y\) 交换且 \(x < y < n\),假设到 \(y+1\) 时花费为 \(k\),若 \(a_x + 2 \leq k\) 可以交换到 \(y+1\) 后往前,若 \(k<a_x+2\) 则可以不与 \(y\) 交换而是与 \(y-1\) 交换。所以结论成立。
然后的步骤是容易的。对于每个 \(i\) 枚举最后一次交换到 \(i\) 的是哪个数,可以直接做到 \(O(n^2)\) 求每个前缀。注意到这个东西很容易李超线段树优化,这里的李超树是全局加线段,复杂度 \(O(n \log n)\)。
CF2108E
经典套路题。
考虑删掉边后怎么计算答案,这个是经典的 \(\sum \limits_{i} \min(sz_i,n-sz_i)\),上界容易证明,构造是选出重心后两两匹配。
对于原题,以 \(1\) 为根,对于每条边最终的贡献要么是 \(\min(sz_i,n-1-sz_i)\),要么是 \(\min(sz_i-1,n-sz_i)\),删掉某条边后这个贡献是很容易直接计算的,然后求出答案后直接按上述方案构造就行了。复杂度 \(O(n \log n)\)。
CF2108F
很厉害。
我们声称若可以得到序列 \(a_1,a_2,\cdots,a_n\),则可以得到任意 \(b_1,b_2,\cdots,b_n\),满足 \(b_i \leq a_i\),证明可以考虑首先容易证明在 \(a_1,a_2,\cdots,a_{n-1}\) 不变的情况下 \(a_n\) 可以随意减小,因为只需要调整 \(n\) 被推倒的时间即可。然后往前归纳就可以说明每个点的值都可以任意减少。
从而如果序列的 \(\mathrm{MEX}\) 可以为 \(x\),则同样可以为 \(x-1\),于是可以二分答案,并判定 \(0,0,\cdots,0,1,2,\cdots,x-1\) 是否可以被操作。从前往后考虑推倒每个数并对后面维护一个区间加即可。总复杂度 \(O(n \log n)\)。
CF2104F
计算本质不同数量,对每种结果钦定一个代表元,这题中对于生成字符串 \(s\) 选取最小的 \(x\) 使得 \(S(x)=s\),然后可以打个表观察一下代表元的要求。然后可以得到一个基于分类讨论的结论,每一类都可以直接计算或者数位 DP,可以做到 \(n=10^{10^5}\) 量级,不仅限于 \(10^9\)。
CF2104G
原图是一个内向基环树森林,不难看出每个基环树的答案为 \(k^{v-c}\),其中 \(v\) 表示点数,\(c\) 表示环上边数。
对 \(3\) 取模,考虑欧拉定理,可以发现答案只和 \(v-c\) 奇偶性有关,离线下来做线段树分治肯定是可以做的,当然直接 LCT 也行。
5.9 模拟赛
T1
考虑对于任意 \(x\),序列中至少能凑出 \(\min(k-1,\lfloor \dfrac{n}{x} \rfloor)\) 个 \(x\),枚举 \(x\) 从 \(1\) 开始,记录前面的总和 \(sum\),则至多贡献 \(\lfloor \dfrac{sum}{x} \rfloor\),然后还需要填相差这么多个 \(x\),复杂度不对但是可以简单优化一下。
T2
T3
显然需要逐位确定答案,问题转化为每次在目前字符串末尾加一个字符,求有多少种结果使得这个串为某个前缀。
暴力做法是枚举这个前缀从哪个点被断开。
考虑到 \(S\) 与这个前缀匹配的最长位置是容易确定的,考虑后面本质上是加了一段 \(T\) 的子串,不难发现这些子串是 SAM 上的一条祖先后代链,只需要提取出上下端点就可以简单计算答案,下端点可以在匹配过程中直接维护,上端点可以倍增。
5.10 模拟赛
T1
考虑从小到大插入 \(a\),维护目前前缀构成的连续段。记 \(f_{i,j,k,0/1/2}\) 表示插入了 \([1,i]\),有 \(j\) 个连续段,目前距离和模 \(m\) 余 \(k\),目前确定的开头与末尾总数为 \(0/1/2\) 的总方案数,转移分为新开一段,加入某段开头或末尾,以及合并两段。总复杂度 \(O(n^2m)\)。
T2
先忽略删去中间某个操作的情况,然后考虑把 \(x,y\) 拆开分别维护,但是你并不能真正的分开因为要求的是 \(\sum x_i \times y_i\),但并不影响分析。
不难发现整个过程中 \(x,y\) 两维分别的相对顺序不会发生变化,容易求出每个 \(i\) 在经过所有操作后得到的 \(x'_i,y'_i\)。
对于挖掉中间某个操作,我们猜测存在 \(a,b\),使得若 \(x_i \leq a\),则 \(x''_i = x'_i - 1\),若 \(x_i \geq b\) 则 \(x''_i = x'_i+1\),区间 \((a,b)\) 内的数不变。\(y\) 也有相同的结论。事实上这个就是对的,所以如果能求出 \(a,b\) 可以直接二维数点做。
对于求 \(a,b\),有一个做法是直接二分然后查询 \(x\) 经过一段后缀的值是多少,这个可以维护后缀的 \(f(x)\) 的图像,然后总复杂度是 \(2\) 个 \(\log\) 的。
然后考虑怎么优化。后缀这个东西本质上并不需要求函数值而是只要求平缓的段,然后前面你可以线段树上二分,查询是后缀两个数是否值相同,维护一个并查集可以做到 \(O(n \log n \alpha(n))\),应该没错吧?
T3
5.12 模拟赛
T1
如果所有点度数为偶数,跑个欧拉回路出来每三个匹配一组即可。
否则考虑尝试把度数为奇数的点干掉,每次取 \(a\) 为目前度数为奇数中度数最小的点,随机取邻点 \(b\),然后随机取 \(b\) 的邻点 \(c\),然后取 \(c\) 的邻点 \(d\),要求 \(d\) 的度数尽可能为奇数,然后删掉三条边。
T2
很深刻的题。
首先不难证明集合中存在某个数的绝对值为目前 \(x\) 的最大值减次大值。原因大概是说不妨考虑集合中存在正数,则最大值必然是取全部正数,次大值要么是删去一个正数,要么加上一个负数,显然这个差的绝对值就是那个正数或负数的绝对值。
然后有一个结论,将集合 \(S\) 中某个数 \(k\) 符号取反,相当于将 \(x_i\) 向左平移 \(k\) 格。证明大概是说你考虑撤销背包的过程,将 \(k\) 删掉,然后加入 \(-k\),把式子化简一下即得。
所以不难发现我可以逐步确定集合中所有数的绝对值构成的集合,具体来说每次取最大值减次大值,假设其为正数,然后做撤销背包。显然平移不影响元素相对顺序与差,所以整个原可重集每个数的绝对值构成可重集可以唯一确定。
然后考虑确定每个数的符号,发现做完上述过程,会剩下唯一一对 \((x,y)\),其中 \(y=1\),若 \(x=0\) 则是一般情况,\(x\neq 0\) 时,本质上是你需要选择若干个数取反,也就是在集合中选取若干个数使得和为 \(x\),这个直接做背包即可。
分析复杂度,最后做背包的时候,状态数显然是 \(O(n)\) 的,容易知道原可重集元素个数为 \(O(\log nV)\) 量级,精细实现可以做到 \(O(n \log nV)\),当然多一两个 \(\log\) 应该也没什么问题。
T3
我不会单位蒙日矩阵。
考虑一般 LIS 求法,从前往后维护一个单增序列,每次加入 \(x\) 时把比 \(x\) 大的最小值替换为 \(x\)。
发现这种方法只能用于在目前序列末尾加入一个数,所以我们希望分析在序列前端加一个数的情况。
记目前得到的单增序列为 \(a\),在序列前加一个数 \(b\),新得到的单增序列为 \(a'\),不难发现 \(a\) 是 \(a'\) 的子序列,且 \(|a'|=|a|\) 或 \(|a'|=|a|+1\),证明是考虑记之前序列最左端的值为 \(y\),分析加入 \(x\) 与 \(x,y\) 得到的结果,不难证明两个长度差至多为 \(1\) 的,其中一个是另一个子序列的两个序列,在末尾加入任意一个数后,仍然符合这个限制。
考虑对原序列扫描线,假设目前扫到 \(r\),我们知道对于 \([1,r],[2,r],\cdots,[r,r]\) 这 \(r\) 个 \([1,r]\) 的后缀,和任意一个数 \(x\),\(x\) 在这 \(r\) 个后缀的结果序列中出现的是一段前缀,形如 \([1,r],[2,r],\cdots,[x,r]\),原因是上面证明了 \([i,r]\) 是 \([i-1,r]\) 的子序列,于是我们只需要能维护 \(x\) 构成的可重集 \(S\),那么查询就是求 \(S\) 中大于等于 \(l\) 的数的个数。
考虑 \(r \gets r +1\),对于 \(S\) 的影响是什么。记 \(p_{r+1}=x\),\(cnt_i\) 表示 \(i\) 在 \([1,r],[2,r],\cdots,[r,r]\) 的生成序列中出现次数和,则我们可以发现整个修改过程大概是,\(cnt'_x \gets r + 1\),然后找到第一个 \(y>x\) 使得 \(cnt_y > 0\),\(cnt'_y \gets 0\),找到第一个 \(z > y\) 使得 \(cnt_z > cnt_y\),\(cnt'_z \gets cnt_y\),以此类推。发现对于可重集 \(S\),相当于是删掉了一个数添加了一个数。
于是整个过程转化为维护一个序列 \(cnt_1,cnt_2,\cdots,cnt_n\),有 \(n\) 次修改和查询,每次给定 \(x,y\),依次对于每个 \(i \geq x\),若 \(a_i > y\),则交换 \(a_i,y\),查询最终 \(y\) 的值。这个是回转寿司,具体做法是分块,每个块维护块内数构成的集合,发现 \(y\) 经过整块时相当于把最大值和 \(y\) 交换,对于散块需要重构得到整个块从前往后的值,不难发现对于一个整块进行若干次操作,按照任意顺序执行这个操作,这个整块最终结果不变,于是对于整块打标记,维护一个小根堆,重构时从前往后取出最小值和目前的数交换即可。
总复杂度 \(O(n\sqrt n \log n + q \log n)\)。
5.13 模拟赛
T1
手玩可以得到一个简单方法:递归构造,每次分半,然后可能需要最后翻转这个区间。
T2
T3
很厉害的观察性质题。
记 \(x\) 为树的重心,以 \(x\) 为根考虑树。
记 \(x\) 的所有儿子子树大小最大值为 \(y\),不妨假设 \(w \geq b\)。
考虑若 \(w > y\),则白点连通块必然经过 \(x\),而黑点必然被逼到某棵子树内。枚举黑色点被逼到了点 \(u\) 的子树,则要求 \(w > f_{fa_u}\),\(f_u\) 表示以 \(u\) 为根,\(u\) 的所有儿子的子树大小最大值。这是因为若 \(w \leq f_{fa_u}\),则可以将白点调整至不包含 \(fa_u\),从而黑点并没有被逼到 \(u\) 子树内,反之则黑点在 \(u\) 子树内必然是一个新的等价类。这类贡献容易计算。
另一方面,若 \(w \leq y\),发现如果存在一个点 \(u\),使得其存在三个儿子的子树大小分别 \(\geq w\),\(\geq w\),\(\geq b\),则任何两种选 \(w,b\) 的方案都可以调整成一样,此时答案为 \(1\),反之可以证明答案为 \(2\),这个是因为你不妨钦定有一种颜色的连通块覆盖 \(x\),然后另一个颜色连通块在那个 \(\geq w\) 的子树内,显然只有覆盖 \(x\) 的颜色为白或黑两种情况,其余情况都可以调整成一个等价类,所以答案为 \(2\)。计算贡献是比较简单的。
整个题可以做到 \(O(n)\)。
P12461
图上比较困难,但是依次对于 \(i=1,2,\cdots,n\),将 \(i\) 的邻点放在序列末尾,则操作变成区间 \(w_{a_i}\gets w_{a_i}+v\),查询区间 \(w_{a_i}\) 的和。
考虑序列分块,将修改对查询的贡献拆成四部分。
- 散块对散块,修改查询暴力遍历散块即可。
- 整块对散块。离线枚举整块,则容易前缀和求出一个区间与这个整块的 \(\sum c1_x c2_x\),然后修改时维护一下这个整块总共被加了多少即可。
- 整块对整块,这个和上面是一样的。
- 散块对整块,同样地,离线枚举整块,修改时把散块的答案往整块上加即可。
时间复杂度 \(O(n\sqrt n)\),空间复杂度线性。
P12472
先忽略 \(S_1,S_2\) 的限制,则等价于 AGC055D,结论是记 \(A\) 为前缀最大 A 数量减 C 数量,\(B\) 为前缀最大 B 数量减 A 数量,\(C\) 为前缀最大 C 数量减 B 数量,则字符串合法等价于 \(A+B+C \leq n\) 且 A,B,C 出现次数均为 \(n\)。必要性显然,充分性考虑将字符串在末尾复制一遍,显然 \(A,B,C\) 不变,然后对于每个 \(i \in [1,n]\),将第 \(i\) 个 A,第 \(i+B\) 个 B,和第 \(i+B+C\) 个 C 匹配,不难证明在长度为 \(6n\) 的字符串中这一个 ABC 是从前往后依次排列的,且任意一个位置 \(i\) 不会在 \(i+3n\) 再次被选中,所以充分性得证。
对于本题,我们之前的结论告诉我们 ABC 子序列数量至少为 \(A\),BCA 子序列数量至少为 \(B\),CAB 子序列数量至少为 \(C\)。我们猜测加入 \(x \in S_1,y\in S_2\) 的限制后,充要条件是满足 \(A+B+C \leq n\),且 \(x \in S_1, y \in S_2\),且 \(x \geq A, y \geq B, n-x-y \geq C\)。事实上这个是对的。
必要性显然,考虑充分性。事实上这等价于对于任意 \(x,y\),若 \(x \geq A,y \geq B,n-x-y \geq C\),且 \(A+B+C \leq n\),则存在划分子序列方式使得存在 \(x\) 个 ABC,\(y\) 个 BCA,和 \(n-x-y\) 个 CAB。考虑对 \(n\) 归纳证明这个结论。如果 \(A+B+C=n\),则唯一可能是 \(x=A,y=B,n-x-y=C\),此时结论显然成立。否则如果 \(x>A\),取出第一个 A,之后的第一个 B,以及之后的第一个 C,考虑如果取不到则可以说明 \(A+B+C \geq n\),否则取出后 \(x \gets x - 1\),\(A,B,C\) 均不会增大,问题变为 \(n - 1\) 的子问题。\(y>B\) 和 \(n-x-y>C\) 同理,所以归纳成立。
直接进行 DP,记 \(f_{i,a,b,A,B,C}\) 表示前 \(i\) 个字符,填了 \(a\) 个 A 和 \(b\) 个 B,目前的 \(A,B,C\) 分别是多少,复杂度 \(O(n^6)\),无法通过。
考虑这样复杂度为什么不对,你发现如果 \(A,B\) 确定,由于没有 \(C \in S_3\) 这样的限制,所以对于 \(C\) 只是有一个上界限定,所以枚举 \(A,B\) 后只需要记 \(f_{i,a,b,0/1,0/1}\) 就能转移,只需要保证转移过程中 \(C\) 不超过上界即可。复杂度 \(O(n^5)\),适当卡常即可通过。
CF2101E
容易看出简单路径的限制并不重要,原因是一条合法路径不可能多次经过一个点,证明显然。
另一方面,路径长度不超过 \(\lceil \log_2 n \rceil\),原因是每次路径长度都翻倍。
所以设状态 \(f_{i,j}\) 表示从点 \(i\) 开始,要走 \(j\) 条边,上一次的边长度至多是多少,转移枚举下一次走的点 \(k\),要求 \(f_{k,j-1} \geq dis(i,k)\),然后 \(f_{i,j} \gets \max(f_{i,j},\lfloor \dfrac{dis(i,k)}{2} \rfloor)\)。这个转移显然可以直接在点分树上通过二分完成,总复杂度 \(O(n \log^3 n)\)。
进一步,对于相同的 \(j\) 和所有 \(i\) 的查询可以离线做,只需要做值域为 \(O(n)\) 的排序即可,复杂度 \(O(n \log^2 n)\)。
CF2101F
考虑异色点最远路径是什么,把无色叶子删掉后求一条直径,考虑直径是怎么样的。如果端点颜色不同那答案就是这条直径长度,否则可以看出必然存在某个异色直径端点是这条直径两端之一,所以答案应该是以直径两端分别为根求出的最大异色点深度。
这个东西仍然不方便刻画,原因是你需要以直径两端分别为根求深度,这是困难的,但是考虑以直径中心为根,则答案必然是半径加上最大异色点深度。给每条边中间加一个点可以保证直径中点不是边,然后枚举中点和半径长度以及最大异色点深度,这样应该是 \(O(n^3)\) 的,应该容易做到 \(O(n^2)\),我没写我不负责。
P12479
二分答案 \(x\) 后,变为求 \(j\) 使得 \(f_{i,j}-jx>0\),\(f_{i,j}\) 为在点 \(i\) 子数内选包含 \(i\) 的 \(j\) 个点构成连通块的权值和最大值。
显然只需要保留 \((f_{i,j},j)\) 上凸的点即可。
考虑 \(f\) 转移是 \((max,+)\),然后由于只需要保留上凸的位置,直接启发式合并维护差分即可。总复杂度 \(O(n \log^2 n)\)。
P6838
考虑直接把 DFS 序记录成答案,但是无法还原,原因是无法区分 \(t\) 是在 DFS 序最后一个儿子子树内还是在父亲的其他子树内。
考虑如果我还知道每个点的出栈时刻,则肯定可以还原了。
但是你没有办法在一个点记录两个值,那咋办。
考虑你其实只需要 \(s\) 的出栈时刻就可以判断到底是在最后一个儿子子树内还是在 \(s\) 子树外,所以只需要知道 \(s\) 的出栈时刻。
另一方面,如果知道所有儿子的出栈时刻,也知道 \(s\) 的入栈时刻,同样可以求答案。
所以考虑将奇数层的点记录入栈时刻,偶数层的点记录出栈时刻,然后离散化到 \(n\) 个数即可。
CF1930H
由于权值是排列,所以路径 \(\operatorname{MEX}\) 等于路径补的点权最小值。
考虑在 \(5\) 次询问内求出路径补的 \(\min\)。
首先考虑 \(L\) 为 \(u,v\) 的 LCA,则 \(L\) 子树外信息可以通过查询 DFS 序前缀和后缀得到。所以这启发我们考虑通过 DFS 序进一步计算答案。
但是 DFS 序并不能完全刻画一条祖先链两侧的信息,具体地,容易发现只能刻画祖先链按照 DFS 顺序中一侧的点。对称的,你只需要 DFS 时记一个后序遍历就可以刻画另一侧的点,然后就是恰好 \(5\) 次。
CF1770H
\(p_i=i\) 时,答案为 \(1\)。
否则可以说明答案为 \(2\),具体地,若 \(p_i=n-i+1\),不难构造答案为 \(2\) 的解。
冒泡排序,初始有 \(p_i=n-i+1\),每次 \(p_i>p_{i+1}\) 时可以交换两条路径交点之后的路径,即可得到任意排列。
CF1019C
考虑增量构造,每次从目前点集 \(S\) 中随便选一个点 \(x\),将 \(x\) 与 \(x\) 出边所有点从 \(S\) 删去,对新的 \(S\) 递归构造后,若所有 \(y \rightarrow x\) 都满足 \(y\) 不在答案中,则将 \(x\) 加入答案。
考虑做法正确性,如果存在 \(y \rightarrow x\) 且 \(y\) 在答案内,显然可以跳过,然后可以发现 \(x\) 的不是被这一次删掉的出边的点必然不会被选择进入答案,所以是对的。
P12545
瞎猜结论题。
考虑把环从某个位置拆成链,不妨假设最大的和的是前缀,最小的和是后缀,然后你考虑选择前缀确定时,后缀可以直接二分求得最优值。你猜测这个关于前缀位置的函数是单谷的,并且谷底随着环断开的位置增大而增大,模拟一下过程即可通过。
感性理解的证明是,单谷看着比较显然,而我把序列开头放到末尾,会导致前缀和变小,那么谷底理应向右移动。
P12546
错误的思考方式是你贪心决策每一次放在左侧还是右侧,但是这个不是很有道理。
显然有一个多项式复杂度的 DP,不知道是几次方的,反正过不去,考虑进一步分析这个 DP。
你考虑直接做这个 DP 需要维护什么信息,需要记录目前到的前缀 \(i\),以及上次两个序列选的位置以及差,考虑能不能把这个状态数减下去。
考虑给每个数一个编号 \(0\) 或 \(1\) 表示其选到了哪个序列,不妨假设现在考虑到了前缀 \([1,i]\),且 \(i\) 的编号为 \(1\)。发现如果 \(i-2,i-1,i\) 中同时有 \(0\) 与 \(1\),则我只需要记录一个状态。具体地,\(f_{i,j}\) 表示最后三个是 \(0,0,1\) 时,上一个 \(1\) 在 \(j\),是否可行。\(g_{i,j}\) 表示最后三个是 \(1,0,1\),上一个 \(0\) 在 \(j\),是否可行。\(h_{i,j}\) 表示最后三个是 \(0,1,1\),上一个 \(0\) 在 \(j\),是否可行。但是可能存在 \(1,1,1\) 的状态,考虑在 \(h\) 向后转移的过程中,直接枚举 \(1\) 连续段结尾在哪里,并且在后面加一个 \(0\),这样就可以假定不存在 \(1,1,1\) 的状态了。
把转移列出来可以知道不需要具体关注 \(f,g,h\) 的值,而只需要知道最大的 \(j\) 满足 \(f_{i,j}=1\),\(g_{i,j}=1\),\(h_{i,j}=1\),直接做就是 \(O(n \log n)\) 的,精细实现一下可能可以做到更优。
P12547
原题的那个最大子段和做法还是太需要注意力了,提供一个不需要动脑的做法。
考虑到后缀限制很丑,把后缀限制改成任意前缀和都小于等于整个序列的和,然后显然可以从前往后贪心,每两个 \(1\) 之间分隔的段中尽量取满。然后很容易得到一个 \(O(nq)\) 的做法。
考虑这个过程中要维护什么信息,本质上是要维护 \(s\) 和 \(s\) 的历史最大值,每次遇到 \(x\) 个 \(-1\) 时,最多取 \(v=\min(x,s)\) 个 \(-1\),然后 \(s \gets s - v + 1\),并更新历史最大值。这个过程显然可以用区间 \((\max,+)\) 矩阵乘法刻画,直接线段树维护,复杂度 \(O(n \log n)\),注意卡一下常。
P12550
简单手玩一下这个过程,比如说有一个 A 和后面的 B 交换了,发现这个 A 不可能再作为 CA 中的 A 和前面交换,而只能和后面的 B 交换,且这个 B 的位置需要小于下一个 C,否则会被挡住。
然后问题等价于序列中选出若干段,每段只包含 AB,BC 或 CA,然后贡献就是每个位置后面的可以和他匹配的字符的数量的和,直接 DP 复杂度 \(O(n^2)\)。
看一下式子可以斜率优化,然后就对了。

浙公网安备 33010602011771号