【2025 暑期】专题题解合集
前言
一天开一个帖子有点太麻烦了,不如专题和模拟赛分开来只写两个帖(
感觉题解写得十分魔怔。尽力了。
并非更好的阅读体验
Day1【贪心、构造、交互、思维】
T1 Minimum OR Path
给定长度为 \(n\) 的序列 \(a\),从位置 \(1\) 开始往后跳,\(i\) 位置能跳到的区间为 \([i, i + a_i]\)。一条路径的代价定义为路径上所有 \(a\) 的或和,求 \(1 \to n\) 的最小代价,或报告无解。
\(n, a_i \leq 5 \times 10^5\)。
线段树优化 DP?对的,对的,你被骗了。要令 \(x ~|~ a_j\) 最小,并不等价于令 \(x\) 最小。
但不难想到按位贪心,判断当前位 \(i\) 是否能不选。
那就把所有 \(a\) 第 \(i\) 位为 \(1\) 的点删掉,看 \(1,n\) 是否联通。
复杂度 \(O(n \log V)\)。
T2 CF1763C Another Array Problem
给定长度为 \(n\) 的序列 \(a\),可以进行若干次操作:选择 \(1 \leq i \lt j \leq n\),把 \([i,j]\) 全部替换成 \(|a_i - a_j|\)。
求经过操作后 \(\sum a_i\) 的最大值。\(n \leq 2 \times 10^5, a_i \leq 10^{12}\)。
\(n \gt 3\) 的时候答案为 \(n \times \max \{ a_i \}\)。
为啥呢?首先找到最大值的位置 \(id\)。大致思路是先把 \(n-1,n\) 清零,把 \(\max\) 移到 \(n\),然后 \([1,n-1]\) 清零,再 \([1,n]\) 都是 \(\max\)。具体细节编一编就行。
\(n \leq 2\) 是简单的,\(n = 3\) 是分讨的,所以也是简单的。
T3 CF2124E Make it Zero
对于长度为 \(n\) 的数组 \(a\),执行尽量少次下列操作,将 \(a\) 清零:
- 构造数组 \(b\) 满足 \(\forall i \in [1, n], 0 \leq b_i \leq a_i\)。
- 满足存在正整数 \(pos \in [1,n]\),使得 \(\sum\limits_{i=1}^{pos} b_i = \sum\limits_{i=pos+1}^{n} b_i\)。
- \(\forall i \in [1,n], a_i \leftarrow a_i - b_i\)。
诈骗!操作次数 \(\leq 17\) 绝对是诈骗!!
诈骗!推了一大堆没有用的性质,绝对是诈骗!!
猜测只需要 \(\leq 2\) 次就可以达成要求。
接下来用 \(S[l,r]\) 表示 \(\sum\limits_{i=l}^{r} a_i\) 现在找一个位置 \(pos\),是满足 \(S[1,pos-1] \geq S[pos+1,n]\) 的最右的 \(pos\)。
或许可以直接 \(pos\) 左右抵消?可是样例就否定了这种做法,详见样例 4。
不妨考虑第一次减的数组 \(b\),把左边选出前后两个子部分,总和分别为 \(a,b\),右边部分选了总和为 \(c\)。则有 \(a=b+c\)。
设左边比右边多了 \(x\),则有 \(a+b-c=x\),接下来不妨钦定 \(c=0\),则有:\(a=b,a+b=2a=x\)。
然后爱怎么构造就怎么构造,比如左边取前后缀 \(a,b\)。(写得好像很抽象,没事我看得懂就行了
T4 QOJ 12150 AGI
有 \(n\) 个区间,表示位置 \(x\) 在该区间内。你要判断每个区间是否正确,要求满足无论 \(x\) 是多少,你都至少判断正确 \(\lfloor \frac{n-1}{2} \rfloor\) 个区间。保证有解。
需要挖掘性质。
- 考虑一个大区间包含小区间,只需要小区间错误,大区间正确即可。
- 如果两个区间不交,只需要都判断错误即可。
接下来剩下的区间就是两两相交,左右端点分别递增。
可以想到按奇偶分类,分别填错误、正确可以最优化答案。维护需要用 set,栈的正确性好像有点问题但它过了。
T5 Gym105484B Birthday Gift
给定一个长度为 \(n\) 的只包含 \(\texttt{012}\) 的字符串。
- 你需要先把每个 \(\texttt{2}\) 替换成 \(\texttt{0,1}\) 中的一个。
- 然后选择两个连续的 \(\texttt{0}\) 或两个连续的 \(\texttt{1}\),并删掉,重复直到不存在连续 \(\texttt{0}\) 或 \(\texttt{1}\)。
问最后留下的字符串长度最小是多少。
杜老师说过:寻找不变量!删除连续两个对于下标奇偶性是没有影响的!
设奇数位的 \(0\) 数量为 \(a\),偶数位 \(0\) 的数量为 \(b\),奇数位 \(1\) 的数量为 \(c\),偶数位 \(1\) 的数量为 \(d\),\(2\) 的数量为 \(e\)。
合理猜测奇偶的 \(0,1\) 可以内部自行配对,\(2\) 可以用来消掉一个 \(0\) 或一个\(1\)。
所以答案为 \(|a-b| + |c-d| - e\),如果变成负数是因为 \(2\) 太多了,需要特判。
T6 CF1153E Serval and Snake
交互题。一个 \(n \times n\) 的网格图内有一条蛇,你可以询问一个矩形,交互库会返回蛇从头到尾进出矩形的次数,你需要在 \(2019\) 次询问内求出蛇头和蛇尾的位置(不区分蛇头尾),\(n \leq 1000\)。
搞笑题,看完就会的那种交互。
给定的交互次数大致是 \(2n\) 再加一些 \(\log\) 的级别,所以容易想到枚举每一行,找出蛇头尾对应是哪两行(对应行返回显然是奇数);如果都是偶数那说明在同一行,那就扫列。
总之最后已知它们在哪两行或哪两列,然后二分一下不难做到 \(2020\)。
最后一步优化是简单的,显然行列只要扫 \([1,n-1]\) 就行了,做到 \(2018\)。
T7 洛谷 P4064 加法
给定长度为 \(n\) 的数组 \(a\),以及 \(m\) 个区间,你需要从中选 \(k\) 个,将这些区间都 \(+d\)。问操作后 \(a\) 中最小值最大是多少。
最小值最大多少,二分答案转判定。
不难想到从前往后,不够就叠区间。但是选哪些区间呢?贪心! 以右端点为关键字大根堆,取能延伸尽量远的区间。做完了。
T8 HDU-6299 Balanced Sequence
给定你 \(n\) 个括号序列,你可以把它们任意排列,拼成一个括号序列,要求这个括号序列的合法括号子序列的最长长度。
首先贪心,这 \(n\) 个括号序列内部能匹配的合法括号对肯定先匹配掉,之后每个括号序列形如 )))))(((((
。括号癌犯了(
设第 \(i\) 个括号序列有 \(l_i\) 个左括号,有 \(r_i\) 个右括号,不难推出如下贪心策略:
- 若存在 \(l_i \geq r_i\) 且 \(l_j \lt r_j\),则 \(i\) 放在 \(j\) 之前。
- 若 \(l_i \geq r_i\),按照 \(r_i\) 升序排序;若 \(l_i \gt r_i\),按照 \(l_i\) 降序排序。
原因是决定匹配数的是 \(l,r\) 更小的那一个,所以如上分类讨论。
T9 洛谷 P2541 Robotic Cow Herd P
有 \(n\) 个序列,每个序列长度不超过 \(10\)。你可以分别从 \(n\) 个序列中选择一个数制作一个机器,花费是所有数字之和。现在要制作 \(k\) 个机器,使得机器选择的数不完全相同,问最小花费。
一个简单的做法是直接记录状态,暴力选最小的往下拓展一位,复杂度大概是高贵的 \(O(nk \log nk)\)。
真的很难想到如下转化:先把所有序列排序,以次小值减最小值为关键字升序排序,用 \((x,y,val)\) 表示一个状态,\([x+1,n]\) 的所有序列选最小值,\(x\) 序列选了第 \(y\) 个,\([1,x-1]\) 的不管。
然后根据题解,可以这样转移状态:
- \(y \leftarrow y+1\),即 \(x\) 序列向下拓展一位。
- \(x \leftarrow x+1, y \leftarrow 2\),即不改变 \(x\),转而将 \(x+1\) 向下拓展一位。
- 当 \(y=2\) 时,将 \(x\) 位钦定为选最小值,\(x+1\) 位选次小值。
不难感性理解这样能覆盖所有情况,我不会证,于是复杂度 \(O(m \log nk)\)。
T10 洛谷 P1852 跳跳棋
数轴上有 \(3\) 颗分别在 \(a,b,c\) 位置的棋子,要通过最少的跳动移动成 \(x,y,z\)。(棋子是没有区别的)
一次“跳动”定义为:任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过 \(1\) 颗棋子,棋子不能重叠。
判断是否能完成任务,如果能则输出最少移动次数。
如果是 \(b\) 往外跳,可以过 \(a\) 也可以过 \(c\),总之就是方案数太多了很难统计。
但如果倒着考虑:\(a,c\) 过 \(b\) 往内跳,由于一次只允许跳过 \(1\) 个棋子,跳的方案是唯一确定的。
所以使用常见套路:初始状态和结尾状态同时往中间状态跳。
每个状态跳到的状态唯一确定,类似于树的父节点?所以问题转化为求 LCA。
若左边距离小于右边距离,则 \(a\) 往右跳;若等于则动不了了;若左边大于右边则 \(c\) 往左跳。
设左右距离较小的是 \(d_1\),较大的是 \(d_2\),则可以一次性跳 \(\lfloor \frac{d2-1}{d1} \rfloor\) 步,且跳完之后新的 \(d_1\) 减半。
于是我们可以在 \(O(\log V)\) 的时间复杂度内找到状态 \((a,b,c)\) 和 \((x,y,z)\) 的所有祖先,接下来 LCA 就不是难事了。
Day2【数据结构 1】
T1 CF1474C Array Destruction
给定长度为 \(2n\) 的序列,初始你可以随意选一个数 \(x\)。你需要执行 \(n\) 次操作,每次从序列中选出两个和为 \(x\) 的数并删掉,把 \(x\) 替换成这两个数中更大的数,问能否通过 \(n\) 次操作清空整个序列。
第一次一定选全局最大值。
但另一个数不知道怎么选,不妨枚举另一个数。然后会发现已知开头两个数之后剩下的决策都是确定的,可以用优先队列或者 set 模拟。
于是时间复杂度 \(O(n^2 \log n)\)。
T2 CF1237D Balanced Playlist
有一个 \(n\) 首歌循环播放的歌单,每首歌有一个好感度 \(a_i\),假设你当前听过歌曲的最大好感度为 \(\text{max}\),则听到一首好感度严格小于 \(\frac{\text{max}}{2}\) 的歌曲你就会退出播放。问从每一首歌开始听你能听多少首歌曲,或报告永远不会退出。
如果全局 \(2 \text{min} \geq \text{max}\) 那就死循环了。
否则经典技巧断环为链,把环复制三遍(原因详见样例 2)。
设 \(f_i\) 表示复制后的序列上,从 \(i\) 开始听最多能听多少首歌曲。不妨先二分 ST 表找到 \(i\) 后面第一个严格 \(\lt \frac{a_i}{2}\) 的位置,然后和 \((i+1) + f_{i+1}\) 比较,取更远的即可。
T3 CF1924B Space Harbour
维护 \(n\) 个空位,支持在某个位置 \(x\) 插入权值为 \(v\) 的物品。定义一个位置的花费为:若该位置有物品则为 \(0\);否则为左边第一个物品的权值 乘 到右边第一个物品的距离。保证 \(1,n\) 这两个位置有物品。
好搞笑的题。
显然是维护一下等差数列就可以了,set 找一下前驱后继即可。
T4 HDU6315 Naive Operations
给定长度为 \(n\) 的排列 \(b\),要求维护一个序列 \(a\),支持如下操作:区间 \([l,r]\) 的 \(a_i\) 加 \(1\);查询 \(\sum\limits_{i=l}^{r} \lfloor \frac{a_i}{b_i} \rfloor\)。
为什么每次只加一?想必是有性质了。
由于 \(a_i\) 每加 \(b_i\) 次,\(\lfloor \frac{a_i}{b_i} \rfloor\) 才会 \(+1\),且 \(b\) 是个排列,不难想到它的变化量是 \(\sum\limits_{i=1}^{n} \lfloor \frac{q}{i} \rfloor\) 的,这是个调和级数。
所以根据线段树势能分析,记一下区间最少再加多少就会有变化,复杂度是 \(O(n \log^2 n)\)。
T5 洛谷 P4587 神秘数
一个可重复数字集合 \(S\) 的神秘数定义为最小的不能被 \(S\) 的子集的和表示的正整数。
现给定长度为 \(n\) 的正整数序列 \(a\),\(m\) 次询问,每次询问包含两个参数 \(l,r\),求 \([l,r]\) 区间所组成的可重集合的神秘数。
先考虑普通集合怎么求神秘数,先升序排序,记一个 \(now\) 表示当前能表示出 \([1,now]\) 的数,每次加入 \(a_i\) 前判断:如果 \(now + 1 \geq a_i\) 则能 \(now \leftarrow now + a_i\)。
换一种表述方法:若 \(\leq now\) 的数之和 \(\text{sum} \geq now\),则 \(now \leftarrow \text{sum}\)。
要求一个区间 \(\leq k\) 的数之和,主席树维护即可。
T6 洛谷 P5268 一个简单的询问
给定长度为 \(n\) 的序列 \(a\),\(q\) 组询问,每组询问给定 \(l_1,r_1,l_2,r_2\),求 \(\sum\limits_{x=0}^\infty \text{get}(l_1,r_1,x)\times \text{get}(l_2,r_2,x)\)。
其中 \(\text{get}(l,r,x)\) 表示区间 \([l,r]\) 中,数字 \(x\) 的出现次数。
首先 \(get(l,r,x)\) 可以转化为前缀和 \(s(r,x) - s(l-1,x)\),\(s(i,j)\) 表示 \([1,i]\) 中 \(j\) 的出现次数。
然后把原式改成前缀和形式,乘出来四项,每一项都形如 \(\sum\limits_{x=0}^\infty s(l-1,x) \times s(r,x)\),可以莫队维护。
Day3【数据结构 2】
T1 CF1208D Restore Permutation
有一个隐藏的长度为 \(n\) 排列 \(p\),现在给定你数组 \(s\),其中 \(s_i = \sum\limits_{j=1}^{i-1} [p_j \lt p_i] \times p_i\),请你还原 \(p\)。
看上去很吓人啊。但你发现可以先确定最后一个数,假设它是 \(x\),则 \(s_n = \frac{x(x-1)}{2}\)。
由此可以推广:从后往前还原,用线段树记录还没被填的数,可以线段树二分 \(O(n \log n)\) 或者二分套树状数组 \(O(n \log^2 n)\) 快速求解。
T2 CF1690G Count the Trains
维护一个长度为 \(n\) 的序列 \(a\),\(m\) 次操作给单点减去 \(d\),求每次操作后全局前缀最小值有几种。
如5 7 3 4 1
的前缀最小值是5 5 3 3 1
,有5 3 1
三种。
好像有很简单的写法,但我不会。所以暴力 Segment Tree!
直接暴力维护前缀 \(\text{min}\) 数组,线段树二分找到更新到的右端点,直接打标记覆盖!
至于计数只需要看一下边界一不一样即可。复杂度 \(O(n \log n)\) 常数稍大。
T3 CF1913D Array Collapse
给定长度为 \(n\) 的序列,元素互不相同。一次操作可以选一个区间,只保留区间的最小值,删除其它数。可以进行 \(0\) 或若干次操作,问操作后的序列有几种。
设 \(f_i\) 表示强制留下 \(i\) 不删,且 \(i\) 是留下数组中最后一位的方案数(不考虑 \([i+1,n]\) 这些数)。
考虑 \(i\) 前面最靠近 \(i\) 且比 \(a_i\) 小的数 \(a_j\),则 \([j+1,i-1]\) 的数都可以作为最终数组倒数第二位。所以有贡献 \(f_i \leftarrow \sum\limits_{k=j+1}^{i-1} f_k\)。
考虑再往前,所有作为前缀最大值的元素 \(j\)。可以从这些 \(j\) 一路往后删除元素,让 \(j\) 成为倒数第二位。
如果用单调栈维护,这些“前缀最大值”其实就是栈内元素,维护栈内 \(f\) 之和即可。复杂度 \(O(n)\)。
T4 CF2000H Ksyusha and the Loaded Set
需要维护一个集合,保证元素不重复。定义“k-空隙”为最小的正整数 \(d\),满足 \([d,d+k-1]\) 都没有在集合内出现。
\(m\) 次操作,支持插入删除元素 \(x\)、查询“k-空隙”。
查询 \(x\) 和它后继之差可以直接 set 简单维护,记为 \(\text{nxt}(x)\)。
用线段树维护,位置 \(x+1\) 的权值为 \(\text{nxt}(x)\),为了方便可以事先插入 \(0,\infty\),线段树二分即可。
T5 洛谷 P7706 文文的摄影布置
给定两个长度为 \(n\) 的序列 \(a,b\),支持 \(m\) 次操作,有三种操作:单点修改 \(a\)、单点修改 \(b\),给定 \(l,r\) 求 \(\displaystyle \max_{l \leq i \lt i+1 \lt k \leq r} \{ a_i + a_k - \min_{j=i+1}^{k-1} b_j \}\)。
看上去就很线段树吧,考虑记录什么信息以及如何合并。
主要问题是 \(j\) 在左区间还是右区间,所以考虑记录区间最大 \(a\)、区间最小 \(b\)、前缀最大 \(a-b\)、后缀最大 \(a-b\)、区间最大形如 \(a-b+a\) 的答案。
合并类似于最大子段和。
T6 CF1638E Colorful Operations
有 \(n\) 个位置,每个位置有两种属性颜色和权值,执行 \(m\) 次操作,有三种:全局某种颜色权值加 \(d\)、区间 \([l,r]\) 覆盖为颜色 \(c\),单点询问权值。
特意去学了珂朵莉树。然后做完了。
珂朵莉树基于“颜色段均摊复杂度分析”,用 set 维护颜色相同的连续段,以及连续段信息。
记得 node
里面要写 mutable
,以及区间操作要先 \(\text{split}\) \(r+1\) 再 \(l\)。
T7 洛谷 P6617 查找 Search
有 \(n\) 个空位,每个空位可以放一个物品。你需要维护数据结构支持以下操作:把第 \(x\) 个空位内物品编号换成 \(d\);询问 \([l,r]\) 是否存在编号之和为 \(w\) 的两个物品。
其中 \(w\) 对于 \(m\) 次询问是常量,强制在线。
考虑没有修改怎么做,记 \(nxt_i\) 表示 \(i\) 后面第一个编号为 \(w-a_i\) 的物品的下标,查询 \([l, r]\) 的区间最小 \(nxt_i\) 看是否 \(\leq r\) 即可。
现在问题是修改一个点可能会影响很多 \(nxt_i\),所以不妨转化 \(nxt\) 的定义:若后面第一个 \(a_i\) 比第一个 \(w-a_i\) 更靠左则为 \(n+1\),否则为 \(w-a_i\) 对应的下标。
这样显然是对的,画个图就懂了,于是 set 维护,线段树修改查询即可。
T8 HDU7436 传送
一个 \(n\) 点 \(m\) 边的无向图,每条边有参数 \((u,v,l,r)\),表示在 \([l,r]\) 时间内 \(u,v\) 连边,设 \(ans_i\) 表示能从 \(1\) 出发到达 \(i\) 的时刻之和,求 \(\oplus_{i=1}^{n} ans_i\)。满足 \(n, m, l, r \leq 6 \times 10^5\)。
一眼线段树分治,然后问题变成了如何给连通块权值 \(+d\)。
线段树分治那肯定用可撤销按秩合并并查集,想到做类似于“懒标记”的东西。
先把贡献加在并查集根节点上,撤销的时候再下传,但这样会重复计算贡献(如样例时刻 \(1,2\) 会传到时刻 \(3,4\))所以在合并的时候要预先减去权值。
T9 CF702F T-Shirts
有 \(n\) 件 T 恤,每件有两个参数:质量 \(q_i\) 和价格 \(v_i\)。有 \(q\) 位顾客,第 \(i\) 位顾客有 \(c_i\) 元,每位顾客会按顺序买当前他能买的质量最好的 T 恤,如果有多个质量最好的会从价格更低的开始买,问第 \(i\) 位顾客能买到多少件 T 恤。
先排序。直接模拟是 \(O(nq)\) 的不好优化,考虑离线询问。
然后依次考虑每一件 T 恤,如果它的价格是 \(v\),则对于当前持有 \([v,2v)\) 元的顾客,他们的位置需要调整;对于 \([0,v)\) 的买不起,对于 \([v,\infty)\) 的相对位置无变化。
考虑 FHQ-Treap,暴力将 \([v,2v)\) 这些顾客删除,然后减去 \(v\) 暴力插入即可,对于 \(\geq 2v\) 的打个标记就行。
每一次暴力插入后 \([v,2v)\) 的权值至少减半,所以最多被插入 \(\log V\) 次。
T10 洛谷 P9388 先人类的人类选别
给定序列 \(a_1,\dots,a_n\) ,共 \(m\) 次操作。每次操作给出 \(x,l,r\) ,首先按顺序将 \(a_1,\dots,a_n\) 与 \(x\) 比较,若 \(x>a_i\) 则交换 \(a_i,x\) 的值,处理完这些比较和交换操作后查询 \(\sum\limits_{i=l}^r a_i\) 。
先把区间和转化为前缀和 \(ans_r - ans_{l-1}\)。
然后前缀和是个啥玩意儿?其实是把所有插入过的 \(x\) 和 \([1,i]\) 的数取前 \(i\) 大之和。主席树维护即可。
Day4 【自由补题,好耶】
摸鱼中。
Day5【数据结构 3】
T1 CF459D Pashmak and Parmida's problem
给定长度为 \(n\) 的序列 \(a\),设 \(f(l,r,x)\) 表示 \([l,r]\) 中 \(x\) 的出现次数。
求有多少对 \(l,r\) 满足 \(f(1,l,a_l) \gt f(r,n,a_r)\),且 \(l \lt r\)。
首先 \(f(1,l,a_l)\) 和 \(f(r,n,a_r)\) 拿个桶维护,是好求的,分别设为 \(f_i, g_i\)。
然后二维数点,扫描线一下树状数组就做完了。
T2 CF1849E Max to the Right of Min
给定一个长度为 \(n\) 的排列 \(p\),设 \(maxpos_{l,r}\) 表示 \([l,r]\) 中最大元素的下标。\(minpos_{l,r}\) 为最小元素下标。
求有多少个子数组 \(p_{l,r}\) 满足 \(maxpos_{l,r} > minpos_{l,r}\)。
考虑先单调栈求出每个位置前第一个比它小和比它大的位置。
扫描线!扫右端点,用线段树维护符合条件的左端点的位置。
- 若 \(a_i \gt a_{i-1}\),则 \(a_i\) 有希望成为区间最大值。
- 设它前一个比它大的位置为 \(p\),则 \(l \in [p+1,i-1]\) 这些左端点都符合条件。
- 若 \(a_i \lt a_{i-1}\),则 \(a_i\) 有希望成为区间最小值。
- 设它前一个比它小的位置为 \(p\),则 \(l \in [p+1,i-1]\) 这些左端点都不符合条件,因为右边已经没有最大值了。
符合条件、不符合条件可以刻画成区间覆盖 \(1/0\),每次移动右端点查询全局和。
T3 HDU7284 Easy problem I
维护一个序列 \(a\),有 \(m\) 次操作分为两种:
- 将 \(i \in [l,r]\) 的 \(a_i \leftarrow |a_i - x|\)。
- 求 \(i \in [l,r]\) 的 \(a_i\) 之和。
满足操作 1 的 \(x\) 单调不降。
由于 \(x\) 单调不降,当一个 \(a_i \leq x\) 之后,它再也没有机会 \(\gt x\)。
所以可以记两个线段树,第一个表示 \(\gt x\) 的数字,第二个表示 \(\leq x\) 的数字。
当第一个线段树中存在一个数 \(\lt 0\),则把它的相反数插入第二个线段树,并把它从第一个线段树中删除。
第一棵线段树打区间减法标记,第二棵 \(a_i \to x - a_i\) 比较难刻画,可以看作加乘标记。
最多只会出现 \(n\) 次从第一棵树转移到第二棵树,复杂度正确。
T4 洛谷 P3863 序列
给定一个长度为 \(n\) 的序列 \(a\),\(q\) 次操作,有两种:
- 给 \([l,r]\) 元素加 \(x\)。
- 求过去有多少个时刻 \(a_x \geq y\)。
很难直接做,不如在二维图上刻画。
设横轴为下标,纵轴为时间,则 1 操作相当于下标 \([l,r]\),对应时间 \(\geq t\) 的区域 \(+x\)。
操作 2 相当于查询 \(x\) 下标 \(\leq t\) 的时间有多少个 \(\geq y\)。
换一个角度,横着做扫描线,枚举下标,对时间轴分块。
现在需要做的就是:后缀加,前缀查询 \(\geq y\) 数量。分块可以轻松维护,具体地就是维护每个块内排序后的结果,查询二分即可。
T5 UOJ637 A. 数据结构
给定长度为 \(n\) 的数列 \(a\),\(q\) 次询问若将 \([l,r]\) 全体 \(+1\),全局有多少个不同的数。询问相互独立。
考虑 \([1,n+1]\) 哪些数对 \([l, r]\) 没有贡献,需要满足:\(x\) 在 \([l,r]\) 外没出现,且 \(x-1\) 在 \([l,r]\) 内出现过。
对于前者,只需要取最左最右的 \(x\);对于后者,可以用 set 维护上一个、下一个 \(x-1\) 的位置。
然后就是 \(l \in [x_1, y_1], r \in [x_2, y_2]\),这些区间中 \(x\) 无贡献,投影到二维平面上可以用扫描线做。
T6 CF526F Pudding Monsters
一个 \(n \times n\) 的网格,每行每列恰好有一个关键点。求有多少个 \(k \times k\) 的子正方形也恰好有 \(k\) 个关键点。
加强版:CF193D。
每行每列恰好有一个关键点,可以转化为:第 \(i\) 列的关键点在第 \(p_i\) 行,转化为排列上的问题。
则原问题等价于:求排列 \(p\) 有多少区间 \([l,r]\) 满足 \(\max - \min + 1 = r - l + 1\)。
然后有两种方向可以选择,第一种是硬干 \(\max - \min + 1 = r - l + 1\),另一种基于“点减边”思想,维护连续段数量。
我们选择更好写,且更常用的后者,且该算法可以拓展到前文的加强版。
枚举插入的元素 \(1 \sim n\) 作为 \(\max\),用一个线段树去维护 \(\min\) 为下标对应的连续段数量,先将 \([1,i]\) 区间 \(+1\)。
然后考虑 \(i\) 的加入减少了哪些连续段,即 \(i\) 在排列上的下标为 \(pos\),它可能会和 \(pos-1, pos+1\) 相连。
所以如果 \(pos-1, pos+1\) 已经被插入,那么就把 \([1, a_{pos-1}]\) 或 \([1, a_{pos+1}]\) 区间 \(-1\)。
由于只能是一段,维护左端点代表的 段数最小值 以及 最小值出现次数,如果最小值为 \(1\) 则只有一段,查询对应的数量即可。
推广到加强版就是最小值为 \(2\)。
Day6【字符串 1】
T1 CF176B Word Cut
定义对字符串 \(S\) 的操作为:将其拆分为两个非空部分 \(x,y\),并交换后拼接。给定两个长度为 \(n\) 的串 \(S,T\),求通过恰好 \(k\) 步将 \(S\) 操作为 \(T\) 的方案数。
观察到这个操作和循环移位等价,所以如果能将 \(S\) 变换为 \(T\),最多只需要一步。
基于这个观察,设 \(f_i\) 表示通过 \(i\) 步将 \(S\) 变换为非 \(T\) 的方案数,\(g_i\) 表示通过 \(i\) 步变换为 \(T\) 的方案数。设 \(S\) 有 \(c\) 个循环移位与本身相同(包括不移位),则:
答案为 \(g_k\),复杂度 \(O(n^2 + k)\),可以 KMP 和矩阵快速幂优化到 \(O(n + \log k)\)。
T2 洛谷 P4824 Censoring S
给定两个字符串 \(S,T\),不断从 \(S\) 中删除可能存在的字符串 \(T\) 直到不再存在 \(T\) 子串,求最后的字符串。
容易联想到字符串匹配 KMP,考虑用栈模拟该过程,当一次匹配成功,就从栈中弹出 \(|T|\) 个连续位置。
最后栈中下标组成了答案字符串。
T3 CF1721E Prefix Function Queries
给定字符串 \(S\),\(q\) 次询问字符串 \(T\),求出 \(S+T\)(拼接)后 \([|S|+1, |S|+|T|]\) 这一段的 KMP \(\text{nxt}\) 数组。其中 \(q \leq 10^5, |T| \leq 10\)。
直接模拟可以构造形如 aaaa...
的字符串卡成 \(O(q |S|)\),瓶颈在于每次都可能重新遍历 \(S\) 串。
不妨类似并查集路径压缩,设 \(\text{ed}{i,j}\) 表示 \([1,i]\) 后面加上 \(j\) 字符,最终跳 \(\text{nxt}\) 跳到哪,其实这东西叫做 KMP 自动机。
话说可以直接 Hash 的,但是带一个 \(\log\)。
T4 CF898F Restoring the Expression
给定一个长度为 \(n\) 的数字串 \(S\),要求把它分成三个连续部分 \(a,b,c\),使得在整数意义下 \(a+b=c\)。
一个简单的做法是直接枚举分割点,然后暴力高精度,复杂度 \(O(n^3)\)。
基于一些观察:设 \(a,b\) 中更长的长度为 \(\text{len}\),则 \(c\) 要么长 \(\text{len}\) 要么长 \(\text{len+1}\),这样只需要枚举 \(\text{len}\),枚举 \(a,b\) 哪个更长即可,还是暴力高精度加法 \(O(n^2)\)。
加法很烦人,所以改成哈希就行了,复杂度 \(O(n)\)。
笑点解析:我写了三哈希 \(10^9 + 7, 998244353, 19260817\)。
T5 洛谷 P8131 Gene Folding
给定一个只含 \(ATGC\) 的核苷酸序列,你可以进行若干次操作,操作形如把一段前缀向后翻折,或把一段后缀向前翻折,要求翻折的左右两部分对称,求翻折后核苷酸序列的最小长度。
首先最后剩下的一定是一个连续区间。
我们可以证明前缀和后缀不会相互影响,如果前缀翻过来会翻到后缀,则不妨让前缀自己先翻折,让它的长度到不了后缀。
所以前后缀能翻就翻,可以用 Manacher 求偶回文区间。
T6 洛谷 P4696 Matching
给定长度为 \(n\) 的排列 \(p\) 和一个长度为 \(m\) 的序列 \(a\),求 \(a\) 中有多少个长为 \(n\) 的区间 \([l, r]\) 使得排序后会得到 \(a_{l+p_1-1}, a_{l+p_2-1}, \dots, a_{l+p_n-1}\)。
转化成前驱后继分别在哪个位置,然后可以直接 KMP 做!复杂度是高贵的 \(O(n)\),完虐树状数组!
T7 CF1310C Au Pont Rouge
对于一个长度为 \(n\) 的字符串,有若干种方案把它分成 \(m\) 段连续非空子区间,设一种分组方案的“标签”为这些子区间中字典序最小的子区间对应的字符串。现在给定 \(k\),求所有可能的分组方案中,第 \(k\) 大的标签是什么。
\(k \leq 10^{18}, n, m \leq 1000\)。
\(k\) 很大,但是只有 \(O(n^2)\) 种 子区间,且大小具有单调性,所以不妨先把所有子区间拿下来排序,二分答案。
如何判定是否合法?考虑 DP:设 \(dp_{i,j}\) 表示前 \(i\) 个位置分成 \(j\) 组,使得每组的字典序都 \(\geq mid\),方案数为多少。
转移比较魔怔,可以先把所有 \(\geq mid\) 的子区间拿出来,贡献记在右端点,转移时枚举 \(i\) 对应的左端点即可,但是复杂度是高贵的 \(O(n^3)\)。
事实上优化只需要倒着做就行了,设 \(dp_{i,j}\) 表示后 \(i\) 个位置分成 \(j\) 组的方案数。
为什么?因为字典序是从前往后比较的,如果固定右端点,合法的左端点是零散的;如果固定左端点,合法的右端点是一段后缀。
那么只要记录所有左端点对应 \(\geq mid\) 的右端点后缀即可,转移写一个后缀和可以优化到 \(O(n^2)\)。
T8 CF873F Forbidden Indices
给定字符串 \(s\) 和 \(01\) 序列 \(b\),设 \(f(a)\) 表示字符串 \(a\) 在 \(s\) 中出现,且结尾在 \(b\) 对应下标不为 \(1\) 的次数,求所有 \(a\) 的 \(\max |a| \times f(a)\)。
结尾这个事情比较不人性,所以先 reverse 一下变成开头不为 \(1\)。
然后长得就很像 SA 了,不妨求出 sa 数组和 height 数组(把开头 \(1\) 的下标扔掉),然后发现这东西就是个区间最小值乘区间长度的最大值。
直接处理出 height 每一位前后第一个更小值的位置,这可以用单调栈轻松维护。
T9 CF1202E You Are Given Some Strings...
给你一个字符串 \(t\) 和 \(n\) 个字符串 \(s_1,s_2,\cdots,s_n\)。所有字符串均由小写英文字母组成。
令 \(f(t,s)\) 表示字符串 \(s\) 作为子串在 \(t\) 中的出现次数。例如,\(f(\text{aaabacaa},\text{aa})=3\),\(f(\text{ababa},\text{aba})=2\)。
计算 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^n f(t,s_i+s_j)\)。\(s_i+s_j\) 表示 \(s_j\) 拼接在 \(s_i\) 之后形成的字符串。
看到匹配,多模,想到 AC 自动机。
考虑 \(f_i\) 为 \(t[1,i]\) 在 \(s\) 中多少个字符串作为后缀出现,\(g_i\) 表示 \(t[i,n]\) 在 \(s\) 中多少个字符串作为前缀出现,则答案为 \(\sum\limits_{i=1}^{n-1} f_i g_{i+1}\)。
考虑如何求 \(f,g\),其实同理,以 \(g\) 为例,建立 \(s\) 集合的 AC 自动机,跑一遍 \(t\),把所有失配指针权值相加即可。复杂度线性。
Day7【动态规划 1】
T1 CF1849D Array Painting
给定一个只包含 \(0,1,2\) 的长度为 \(n\) 的数组 \(a\),初始每个位置都是蓝色,你可以执行两种操作:1. 花费一个硬币选择一个蓝色元素,将它染红。2. 不花费硬币,选择一个 \(\gt 0\) 的红色元素和它的一个相邻蓝色元素,将蓝色元素染红。
问最少需要多少个硬币能把序列染红。
设 \(dp_{i,j}\) 表示染红了 \([1,i]\),其中 \(a_i\) 还剩 \(j\),所花费的最少硬币数。
考虑让 \(i-1\) 染红 \(i\):\(dp_{i,a_i} = \min\{ dp_{i-1,1}, dp_{i-1,2}, dp_{i-1,0} + 1 \}\)。
考虑让 \(i\) 一路往前染,设 \(pre_i\) 为 \(i\) 前面第一个 \(0\) 的下标:\(dp_{i,a_i - 1} \leftarrow dp_{pre_{i-1}, 0}\)。显然不需要考虑 \(dp_{pre_{i-1},1/2}\),因为这样更优且在 \(pre_i\) 已经被考虑过了。
T2 CF1458B Glass Half Spilled
有 \(n\) 个玻璃杯,第 \(i\) 个容量为 \(a_i\) 实际有 \(b_i\) 的水。当你从 \(i\) 杯往 \(j\) 杯倒入 \(x\) 单位的水时,会损失 \(\frac{x}{2}\) 的水,\(j\) 杯最后会有 \(\min(a_j, b_j + \frac{x}{2})\) 的水。
对于所有 \(k \in [1,n]\),你可以进行任意次操作,操作后由你 \(k\) 个杯子使得它们的 \(b\) 之和最大。\(n, a_i, b_i \leq 100\)。
显然选 \(b\) 最大的那 \(k\) 个杯子,且显然 \(a \to b \to c\) 不如直接 \(a \to b\) 优,即不会出现 \(\geq 2\) 次转移的水。
设 \(all\) 为初始 \(\sum b_i\),\(lim\) 为选中的 \(\sum a_k\),\(sum\) 为选中的 \(\sum b_k\),则可以把没选中的水都倒入选中的水中,最后贡献是:\(\min(lim, sum + \frac{all - sum}{2}) = \frac{ \min(2lim, all + sum) }{2}\)。
不难想到设 \(f_{i,j,s}\) 为前 \(i\) 个杯子,选了 \(j\) 个,\(lim\) 为 \(s\) 的最大 \(sum\) 是多少,最后枚举所有合法状态统计答案,要 \(\div 2\),复杂度 \(O(n^4)\)。
T3 CF1077F2 Pictures with Kittens (hard version)
给定一个长度为 \(n\) 的序列 \(a\),你需要从中选出恰好 \(x\) 个元素,使得 \(a\) 中每连续的 \(k\) 个都至少有一个被选中。\(n \leq 5000, a_i \geq 1\),求选出元素最大的 \(\sum a\)。
显然设 \(f_{i,j}\) 为选了 \(i\) 个,第 \(i\) 个选出的是 \(a_j\) 的最大总和,转移枚举 \(l\) 表示 \(i-1\) 选了 \(l\),\(l \in [j-k,j-1]\),\(O(n^3)\)。
然后发现 \(l\) 的范围是一个长度固定的区间,直接单调队列优化到 \(O(n^2)\) 就做完了。
T4 CF1874C Jellyfish and EVA
两位总司令在驾驶外星飞船前往星战前线,星图有 \(n\) 个点 \(m\) 条有向边,保证所有有向边 \(u \to v\) 满足 \(u \lt v\)。
每次愚蠢的总司令 B 会随机选一条边,聪明的总司令 A 也会选一条边,若选的边相同则飞船可以通过该边;否则这两条边会“不可以,总司令!”然后服务器繁忙,请稍后再试,拒绝访问。
如果两位总司令所在的点没有边可以选择,则它们坠机了。求总司令 A 在最优操作下从 \(1\) 号点到达 \(n\) 号点的最大概率。
构成一张 DAG,而且涉及概率,考虑倒着做概率 DP,设 \(f_i\) 表示总司令在 \(i\) 要去 \(n\) 的最大概率。
一个点 \(u\) 从它的后继 \(v\) 转移而来一定是有规律的,不然这也太逆天了。
合理猜测规律是每次总司令 A 选 \(f\) 最大的 \(v\),后面推导印证这个猜测是对的。
先将 \(v\) 按照 \(f\) 降序排序。
设 \(dp_{i,j}\) 表示现在还剩下 \(i\) 条边,你要选择第 \(j\) 大走概率是多少。
由于总司令 A 肯定选最大的(\(1\)),考虑总司令 B 选了什么。
- 显然 \(j\) 不能被选,不然第 \(j\) 大的边就直接被炸毁了。
- 若选了 \(1 \lt k \lt j\),则概率为 \(\frac{j-2}{i} \times dp_{i-2,j-2}\)。
- 否则选 \(j \lt k \leq n\),则概率为 \(\frac{i-j}{i} \times dp_{i-2,j-1}\)。
然后从后往前求 \(f\),将 \(f_v\) 乘上对应的 \(dp\) 权值即可。
T5 QOJ 11110 Witnessing the Miracle / 见证奇迹
给定两个长度为 \(n\) 包含
01?
三种字符的字符串,你需要将?
替换成0
或1
,然后对第一个字符串进行 \(k\) 次如下操作,使其和第二个字符串相等。
选择一个 \(1\),将它左边所有 \(1\) 左移一位,右边所有 \(1\) 右移一位,然后删掉它。
注意我们定义字符串“相等”只需要满足 \([1,n]\) 内的字符串匹配,\((-\infty,0]\) 和 \((n,\infty)\) 的部分忽略不计。
将两个字符串命名为 \(S,T\)。
考虑设 \(dp_{i,j}\) 表示考虑 \(S\) 的前 \(i\) 位,操作 \(j\) 次的方案数。
- 如果 \(S_i\) 可以是 \(0\),那么要求它位移以后的位置也必须是 \(0\)。
- 如果 \(S_i\) 可以是 \(1\):
- 如果不操作 \(i\),那么要求它位移以后位置必须是 \(1\)。
- 否则要求位移以后的位置及其左右相邻必须是 \(0\),因为操作后两边不可能再是 \(1\)。
满足条件转移即可。
Day8【自由补题,好耶】
摸鱼中。
Day9【动态规划 2】
T1 CF1324E Sleeping Schedule
每天有 \(h\) 小时,你会睡 \(n\) 次觉,每次有一个参数 \(a_i\)。你可以选择在 \(a_i\) 或 \(a_i-1\) 小时后入睡,若入睡时间在 \([l,r]\) 之间则这次睡眠是好的,问最多能有多少次好的睡眠,\(n, h \leq 2000\)。
直接设 \(dp_{i,j}\) 表示前 \(i\) 次睡觉,第 \(i\) 次在 \(j\) 入睡最多有多少个好的睡眠即可,复杂度 \(O(nh)\)。
T2 CF2000F Color Rows and Columns
有 \(n\) 个矩形,第 \(i\) 个矩形大小为 \(a_i \times b_i\)。你可以进行若干次操作,每次可以给一个矩形的一个单元格染色,你的得分为被完整染色的行列总数,问获得至少 \(k\) 分至少需要几次操作。\(n \leq 1000, k, a_i, b_i \leq 100\)。
先求出 \(f_{i,j}\) 表示第 \(i\) 个矩形获得 \(j\) 分最少的操作次数,这很好做,直接枚举长宽。
然后设 \(g_{i,j}\) 表示前 \(i\) 个获得 \(j\) 分的最少操作次数,转移枚举第 \(i\) 个获得几分,复杂度 \(O(n k^2)\)。
T3 CF1557D Ezzat and Grid
有 \(n\) 个 \(\texttt{01}\) 串竖着排列,给定 \(m\) 个区间 \(\{i,l,r\}\) 表示第 \(i\) 个串的 \([l,r]\) 都是 \(1\)。你最少要删多少个串才能使得剩下的串任意相邻两个与和不为零,输出方案。\(n, m \leq 3 \times 10^5, l,r \leq 10^9\)。
比较简单,设 \(dp_{i}\) 表示前 \(i\) 个串至少删几个,则枚举 \(j \lt i\) 作为上一个不删的,需要满足 \(i,j\) 与和不为零。
这个东西直接线段树搞一下就好了,插入 \(dp_i - i + 1\),查询 \(i\) 区间最小值即可。
输出方案就记一个 \(\text{pair}\),表示从哪里转移而来。
T4 CF780F Axel and Marston in Bitland
给定一张无重边有向图,每条边为 \(0\) 或 \(1\)。构造字符串数组 \(s\),其中 \(s_{0} = \texttt{0}\),\(s_i\) 为 \(s_{i-1}\) 和 \(s_{i-1}\) 取反后拼接的字符串。如 \(s_{2} = \texttt{0110}\)。
从 \(1\) 出发,要求走的边权序列是 \(s_{\infty}\) 的前缀。
考虑倍增,设 \(f_{i,j,k}\) 表示 \(j \to k\) 走 \(2^i\) 步,第一步是 \(0\) 是否可行;\(g_{i,j,k}\) 表示第一步是 \(1\)。这个东西的计算复杂度是 \(O(n^3 \times 60)\),但是可以 bitest 优化到 \(O(\frac{n^3 \times 60}{\omega})\) 接近 \(O(n^3)\)。
然后设 \(h_{i,j,0/1}\) 表示只考虑 \(\geq i\) 的倍增,从 \(1\) 走到 \(j\) 下一步是 \(0/1\) 的最长路,直接常规转移即可。
T5 QOJ 9879 ReTravel
一个二维平面上有 \(n\) 个点,你需要按顺序访问这些点(只要求访问序列的一个子序列是 \(1 \dots n\) 即可)。
你可以花费 \(1\) 代价执行 \(x \leftarrow x + 1\),或花费 \(1\) 代价 \(y \leftarrow y + 1\),或不花费代价撤销一步操作。求最少花费。
不难想到区间 DP,设 \(f_{i,j}\) 表示从 \((\min\limits_{k=i}^{j} x_k, \min\limits_{k=i}^{j} y_k)\) 访问 \([i,j]\) 的最小代价。
如果把 \((0,0)\) 看作“根节点”,访问路径是一棵树,所以直接枚举一个类似于 LCA 的东西转移即可。
T6 CF771D Bear and Company
给定一个长为 \(n\) 的大写字母字符串 \(S\),你需要通过任意次交换相邻的两个元素使得字符串中不存在 \(\texttt{VK}\) 子串,求最小交换次数。\(n \leq 75\)。
既不是 V
又不是 K
的元素可以直接看作同一种元素。作如下转化:非 V
非 K
为 \(0\),V
\(\to 1\),K
\(\to 2\)。
\(n \leq 75\) 这件事很牛啊,所以怎么暴力怎么来,考虑设 \(f_{i,j,k,0/1/2}\) 表示放了 \(i\) 个 \(0\)、\(j\) 个 \(1\)、\(k\) 个 \(2\),最后一个是 \(0/1/2\) 的最小交换次数。
冒泡排序交换次数相当于逆序对!所以枚举下一位填什么,看一看有多少个字符本应在它后面现在却在前面,\(O(n)\) 扫一下就可以求出来。
总复杂度 \(O(n^4)\),但是可以前缀和优化到 \(O(n^3)\),数据范围还是开太小了。
T7 CF331C3 The Great Julya Calendar
给你一个 \(\leq 10^{18}\) 的非负整数 \(n\),你需要对它进行尽量少的操作使它变成 \(0\)。
一次操作定义为让 \(n\) 减去它的某一个数位,如 \(24 \to (24 - 2) = 22\)。
打表发现操作次数单调不降,所以不妨重新刻画操作:\(n\) 减去它的最大数位。
\(n\) 这么大又和数位有关,考虑数位优化 DP,设 \(f_{i,j}\) 表示从高到低位考虑,当前最大数位是 \(i\),当前数是 \(j\)。
转移相当于把两段拼在一起。
map< pair<int, long long>, pair<long long, int> > mp;
pair<long long, int> dfs(int mx, long long n) {
if (n <= 9) return {1, n - max(mx * 1ll, n)};
if (mp[{mx, n}].first > 0) return mp[{mx, n}];
long long high = 1; while ((__int128)high * 10 <= n) high *= 10;
pair<long long, int> t1 = dfs(max(mx * 1ll, n / high), n % high), t2 = dfs(mx, n / high * high + t1.second);
return mp[{mx, n}] = {t1.first + t2.first, t2.second};
}
T8 CF1601D Difficult Mountain
全机房都会 2700 了我还在魔怔。
一直在画二维图搞什么数据结构优化 DP,魔怔了一个半小时看了眼题解是贪心……
按照 \(\max(a,s)\) 为第一关键字,\(s\) 为第二关键字升序排序,然后能选就选。
证明还是考虑在二维平面上画出来,相当于按照 \(\max(x,y)\) 分出来若干组,然后考虑选或不选当前这个,分析一下就得到了能选就选。
线段树的话好像还是分 \(s \geq a, s \lt a\) 两类,选所有 \(s \geq a\) 的,考虑选尽量多的 \(s \lt a\),按 \(a\) 升序排序,设 \(dp_i\) 表示山高为 \(i\) 最多有几个人可以通过,单点修改区间最小值可以用线段树维护。
T9 Gym105139D MACARON Likes Happy Endings
将长度为 \(n\) 的序列划分为 \(\leq k\) 段,每段的代价是异或和为 \(d\) 的子区间个数,求最小代价和。
简单 DP 是好做的,然后打表发现 \(w(i,j)\)(区间 \([i,j]\) 的代价)满足四边形不等式。
四边形不等式优化 DP 笔记。
考虑分治转移,然后发现不会算 \(w(i,j)\)。先求 \(s\) 为 \(a\) 的异或前缀和,联想到莫队。
虽然直接莫队的复杂度是错的,但是发现分治的每一层 \(i,j\) 指针单调不降(因为决策单调性),所以对每一层来说这都只是个双指针。
于是单层计算所有 \(w(i,j)\) 的复杂度是 \(O(n)\),总复杂度 \(O(n \log n)\)。
T10 CF311B Cats Transport
详见 斜率优化笔记合集。
Day10【动态规划 3】
T1 CF1096D Easy Problem
给定一个长度为 \(n\) 的字符串,删除第 \(i\) 个字符需要花费 \(a_i\) 的代价,需要用最小的代价使得字符串不包含
hard
子序列。
设 \(f_{i,j}\) 表示前 \(i\) 个字符,hard
子序列匹配到了第 \(j\) 个的最小代价。
转移是简单的。
T2 洛谷 P10156 胜者组
有 \(n\) 个竞赛生,你需要保留至多 \(m\) 个,让剩下的人滚回去学文化课(悲),每个人有一个参数 \(a_i\),所属的组别为 \(c_i\)。
每次你可以钦定两个人 \(i, j\) 结伴滚回去学文化课,需要满足 \(c_i = c_j\),会产生 \(a_i + a_j + x \times |i - j|\) 的冲突值。
求最少冲突值或报告无解。
假设已知 \(f_{i,j}\) 表示 \(i\) 组留下 \(j\) 个的最小冲突值,那么不难想到设 \(g_{i,j}\) 为前 \(i\) 组留下 \(j\) 个的最小冲突值,直接做 DP。
瓶颈在于求 \(f\),想到对于每一组分别 DP:设 \(dp_{i,j,0/1}\) 表示这一组前 \(i\) 个同学留下 \(j\) 个,现在是完整的组还是有一个人没有队友。
转移考虑这个人留下,新建一组还是拼一组。
T3 CF1336C Kaavi and Magic Spell
给定长度分别为 \(n,m\) 的字符串 \(S,T\),你需要按顺序将 \(S\) 中字符串加入一个双端队列的头或尾,要求加入字符次数 \(\in [m,n]\)。
求 \(T\) 是最终队列字符串前缀的方案数。
前缀比较难想,那就简化问题:钦定 \(n=m\),求最终队列恰好为 \(T\) 的方案数。
这容易想到一个区间 DP:设 \(f_{i,j}\) 表示 \(S\) 前 \(j-i+1\) 个字符匹配 \(T [i,j]\) 的方案数,转移枚举字符放左边还是右边,需要满足匹配条件。
然后变成前缀问题,这等价于将 \(T[m,n]\) 都设为通配符,即这个区间内不需要满足匹配条件。
答案即为 \(\sum\limits_{i=m}^{n} f_{1,i}\)。
T4 Gym 104128B Ropeway
一座桥由 \(n+2\) 个点组成,编号为 \([0,n+1]\),某些点必须加固,其余点可以自由选择是否加固,但是相邻两个加固点距离必须 \(\leq k\)。
给定每个位置的加固代价,以及 \(q\) 次询问,每次单点修改代价(询问相互独立),求加固桥梁的最小代价。
\(n \leq 5 \times 10^5, k \leq \min(3 \times 10^3, n+1)\)。
不难写出普通转移方程:\(f_i = \min \limits_{j=\max(0,i-k)}^{i-1} \{ f_j \} + a_i\)。
\(k\) 有上界提示我们复杂度与 \(k\) 相关。
考虑到单点 \(p\) 的代价修改只会影响 \([p-k, p+k]\) 这些位置,所以暴力把这些位置跑一遍 DP,再拼接原有的 DP 数组即可。
需要正反各跑一遍。
T5 CF1242C Sum Balance
给定 \(n\) 个 vector,你需要构造一种方案,从每个 vector 中各选出一个数,然后乱排把这些数分别插入每个 vector,使得每个 vector 数字之和相等。
\(n \leq 15\),每个 vector 最多 \(5000\) 个数,所有数字互不相同。
首先求出 \(\frac{sum}{k}\) 为每个 vector 最后的和。
由于数字互不相同,取出数字之后放入的数字可以唯一确定,不妨连一条有向边。
相当于找出若干环,使得同一个环上没有相同 vector 的数,用这些环覆盖所有 vector,可以状压。
输出方案:状压时枚举子集,求出由哪两个子状态拼起来,最后递归。
T6 CF559E Gerald and Path
有 \(n\) 条线段,每条线段给定其中一端的位置及长度,求所有线段覆盖的最大长度。\(n \leq 100\)。
容易写出一个错误的 DP 转移,然后考虑直接忽略贡献,再到贪心钦定向右。
详见此:题解。
Day11【组合数学 1】
省流:这一点都不组合数学!
T1 CF1436C Binary Search
给定一段二分查询排列中是否存在 \(x\) 的代码(详见题面),求有多少个排列在经过这次二分后能正确找到 \(x\)。
先按照题目模拟,标记有多少个 \(\lt x\) 和多少个 \(\gt x\) 的数,分别记为 \(lt, gt\)。
贡献很明显就是 \(\displaystyle C_{x-1}^{lt} \times C_{n-x}^{gt} \times lt! \times gt! \times (n-lt-gt-1)!\)。
T2 洛谷 P9306 进行一个排的重 (Minimum Version)
有 \(n\) 个二元组,第一关键字和第二关键字分别是 \(1\) 到 \(n\) 的排列,现在你可以任意排二元组顺序,要求两个关键字分别的前缀最小值数量之和最小,求最小值以及方案数。
贪心地想就是把大的放前面,因此可以钦定其中一个排列把 \(n\) 放在第一个。
对于另一个排列,如果刚好也把 \(n\) 放在第一个那答案就是 \(2\),否则一定可以把 \(n\) 放在第二个让答案最小为 \(3\)。
然后考虑计算方案数,设另一个排列的第一个是 \(x\),则只要保证 \(n\) 在所有 \(\gt x\) 的数里面排第一个就行了,方案数 \(\frac{(n-1)!}{(n-x)!}\)。
T3 CF1696E Placing Jinas
给定一个长度为 \(n\) 的单调不增序列 \(a\),对于一个二维平面,若 \((x,y)\) 满足 \(0 \lt y \leq a_x\) 则这个点为白色,否则为黑色。最初有一个玩偶在 \((0,0)\),每次你可以将白色位置 \((x,y)\) 的玩偶删掉,它会分裂,在 \((x+1,y), (x,y+1)\) 两个位置各新增一个玩偶,一次操作你只能删一个位置的一个玩偶,问你要操作几次才能让白色区域没有玩偶。
设 \(f{i,j}\) 表示 \((i,j)\) 曾经有多少个玩偶,则有 \(f_{i,j} = f_{i-1,j} + f_{i,j-1}\)。
相当于从 \((0,0)\) 走到 \((i,j)\) 的方案数,可以用组合数刻画:\(f_{i,j} = \binom{i+j}{i}\)。
然后要求 \(\sum\limits_{i=1}^{n} \sum\limits_{j=0}^{a_i} f_{i,j} = \sum\limits_{i=1}^{n} \sum\limits_{j=i}^{i+a_i} C_{j}^{i}\),这个直接用组合数前缀和搞一下就可以优化到 \(O(n)\)。
T4 CF571A Lengthening Sticks
有三根木棍长为 \(a,b,c\),你有一个参数 \(l\),你可以给三根木棍分别加上 \(x,y,z\) 的长度,但是要满足 \(x+y+z \leq l\),且加长后三根木棍能组成三角形,求方案数。
正着推了半天,总之有一堆细节,但是反过来就清晰很多。
考虑用总数减去不合法的方案数,总数考虑隔板法,将 \(l\) 长度分成 \(4\) 份,方案数为 \(C_{l+3}^{3}\)。
然后枚举哪根木棍不合法(超过了另外两根木棍之和),假设是 \(c+z\) 不合法。
则 \(c+z \geq a+x+b+y, x+y \leq l-z\),可以得到 \(x+y\) 的一个上界 \(\text{lim}\),然后再对 \(\text{lim}\) 做一个隔板法就可以求出 \(x,y\) 的方案数:\(C_{\text{lim}+2}^{2}\)。
T5 CF1929F Sasha and the Wedding Binary Search Tree
有一棵二叉搜索树,每个点 \(u\) 有 \(\in [1,C]\) 的权值 \(a_u\),如果 \(a_u=-1\) 则说明权值未确定。你需要给未确定的点填入权值,使得权值都在 \([1,C]\) 之间且满足二叉搜索树性质。
什么二叉搜索树都是唬人的,中序遍历一下转化成序列问题。
考虑相邻两个确定值的点之间怎么填,现在变成一个 \(len\) 个空位,填数 \(\leq v\),且填的要单调不降,问方案数,最后再乘法原理组合起来即可。
这个子问题是简单的,和 T3 差不多,也是先写出 \(O(nv)\) 的式子再组合数前缀和,不再赘述。
T6 CF1227F2 Wrong Answer on test 233 (Hard Version)
有长度为 \(n\) 的数组 \(a\) 和 \(b\),每个元素都 \(\in [1,k]\),给定你 \(a\),你需要对 \(k^n\) 种数组 \(b\),求出有多少种 \(b\),使得它和 \(a\) 匹配的位置数严格小于 \(b\) 顺时针循环位移一格后与 \(a\) 匹配的位置数。
考虑一个 \(O(n^2)\) 的 DP:设 \(f_{i,j}\) 表示前 \(i\) 个位置,权值和为 \(j\) 的方案数。其中“权值”定义为:若 \(b_i = a_i\),则权值 \(-1\);若 \(b_i = a_{i+1}\),则权值 \(+1\)。
如何转移?
- \(h_i = h_{i+1}\):权值无变化,\(k \times f_{i,j} \to f_{i+1,j}\)。
- \(h_i \not= h_{i+1}\):
- \(f_{i,j} \to f_{i+1,j-1}\)。
- \(f_{i,j} \to f_{i+1,j+1}\)。
- \((k-2) \times f_{i,j} \to f_{i+1,j}\)。
这东西非常难优化,但是发现 \(f_{i,j} = f_{i,-j}\)(可以把环反过来,本质是相同的),所以考虑容斥:求出 \(f_{i,0}\),用总数减掉再 \(\div 2\)。
先求出有多少个 \(i\) 满足 \(a_i = a_{i+1}\),设有 \(m\) 个。然后枚举有多少 \(b_j \not= a_j\) 的,设有 \(i\) 个,则也有 \(i\) 个满足 \(b_j = a_{j+1}\)。
先组合数选出下标,剩下的随便排,则方案数为:\(\displaystyle \sum\limits_{i=0}^{\lfloor \frac{n-m}{2} \rfloor} C_{n-m}^{i} \times C_{n-m-i}^{i} \times (k-2)^{n-m-2i}\)。
T7 洛谷 P7118 Galgame
规定比较两棵二叉树的“规则”:若大小不同,则大的那个更“有趣”;递归比较左子树;若左子树完全相同,则递归比较右子树。
给定一个 \(n\) 节点的二叉树,求有多少种二叉树不比它“有趣”。
考虑一个 \(O(n^2)\) 的 DP:设 \(f_u\) 表示 \(u\) 子树和给定树大小相同,这个子树有多少二叉树不比它有趣。
其中 \(\text{Cat}(i)\) 表示卡特兰数第 \(i\) 项,意义为大小为 \(i\) 的二叉树数量。
第一项 \(\sum\limits_{i=0}^{sz_{ls}-1} \text{Cat}(i) \times \text{Cat}(sz_u-i-1)\) 表示左子树大小不够大;第二项 \(\text{Cat}(sz_{rs}) \times f_{ls}\) 表示左子树递归比较出了大小,右子树任意;第三项 \(f_{rs}\) 表示左子树完全相同,比较右子树。
然后观察半天发现这东西无法多项式优化,看上去也和什么根号分治毫无关系,其实可以启发式。
计算瓶颈主要在于第一项,复杂度是 \(O(n^2)\)。但是卡特兰数有如下性质:\(\text{Cat}(n) = \sum\limits_{i=0}^{n-1} \text{Cat}(i) \times \text{Cat}(n-1-i)\),所以如果 \(sz_{ls} \leq sz_{rs}\) 直接这么跑,否则容斥,用右子树大小去跑。
复杂度最坏的时候是完全二叉树,是 \(O(n \log n)\) 的。
T8 CF1237F Balanced Domino Placements
给定 \(n \times m\) 的网格和 \(k\) 个 \(1 \times 2\) 的 Domino 骨牌,你可以继续摆放任意多个 Domino 骨牌,但是要求每一行、每一列最多只有一个骨牌,求方案数。
如果只能竖着放,那么只需要枚举放置的骨牌数量 \(c\),设 \(f_{i,j}\) 表示不考虑列的限制,前 \(i\) 行放置 \(j\) 个的方案数。
然后再考虑列的排列数,则答案为 \(\sum\limits_{c} f_{n,j} \times \binom{m}{c}\)。
本题需要观察到行列是相对独立的,所以再设 \(g_{i,j}\) 表示不考虑行,前 \(i\) 列放置 \(j\) 个的方案数。
答案即为 \(\displaystyle \sum\limits_{0 \leq i \leq mm} \sum\limits_{0 \leq j \leq nn} f_{m,i} \times \binom{nn - 2j}{i} \times g_{n,j} \times \binom{mm - 2i}{j}\)。
其中 \(nn,mm\) 为初始没有被覆盖的行列数。
T9 QOJ 10335 Twin Contests
给定 \(n\),对 \(i \in [1,n]\) 的所有 \(i\),求有多少种 \(1 \sim n\) 的排列使得 \(\forall j \in [1, n], i \times p_i \leq j \times p_j\)。
我会 \(O(n^3)\)!枚举 \(i,p_i\),由于 \(p_j \geq \frac{i \times p_i}{j}\) 可以算出 \(p_j\) 的下界,可以先求出每个 \(j\) 有多少种数可以选择。
不妨设有 \(a_j\) 种可以选,那么答案就是 \(\prod a_j - (j-1)\),但是对于 \(i\) 那一项可能需要特判一下 \(\times 1\)。
我会 \(O(n^2 \log n)\)!显然 \(i \times p_i\) 最大值只能取到 \(n\),因为 \(p_1\) 最多也只能是 \(n\)。那么合法的 \((i,p_i)\) 对就是调和级数 \(O(n \log n)\) 对。
我会 \(O(n \log n)\)!考虑枚举 \(s = i \times p_i\),再枚举 \(s\) 的因数 \(i\),将 \(p_i = \frac{s}{i}\) 设为“不可选择”(其实就是少了一个可选的数)。
这个过程中容易维护 \(\prod a_j - (j-1)\),对于 \(i\) 的特判只需要把 \(i\) 那一项除掉就可以了。
\(\color{red}{\text{T10 QOJ 9479 And DNA}}\)
Day12【放假,好耶】
划水中。
Day13【组合数学 2】
T1 CF1795D Triangle Coloring
给定 \(\frac{n}{3}\) 个三元环中每条边的边权,你需要给恰好 \(\frac{n}{2}\) 个点染成黑色,剩下为白色。
定义一种染色方案的权值为:连接两个点颜色不同的边的边权总和,求最大化权值的方案数。
首先一定不会出现三元环三个点同色的情况,因为这样不优。
然后先 \(\binom{\frac{n}{3}}{\frac{n}{6}}\) 选出哪些点涂两白一黑,剩下的两黑一白,接下来如果三条边都相同则 \(\times 3\),否则若次小和最小相同则 \(\times 2\)。
T2 CF1207D Number Of Permutations
给定 \(n\) 个二元组,定义它的一个排列是好的,仅当其中一个关键字是单调不降的。求有多少种排列是好的。
典型的容斥,用总数 \(n!\) 减去不合法方案数。
不合法方案数考虑第一、第二关键字分别单独有序,再容斥回来第一第二同时有序。
T3 CodeChef - Sum of Goodness
定义一个序列的价值为:排序之后 \(a_i = i\) 的位置数量。给定长度为 \(n\) 的序列 \(a\),求它的所有子序列价值和。
考虑拆分贡献,算一个数对答案产生贡献的方案数。
先排序,找出极长段 \([i,j]\) 满足 \(a_i = a_j\),再枚举 \(a_i\) 加入 \(k\) 个,从而算出 \([0,a_i-1]\) 的数要选几个,\(\gt a_i\) 的数随便取。
\([0,a_i-1]\) 选数是 \(O(n)\) 组合数求和的形式,不过可以单指针增量做到 \(O(1)\)。
T4 CF1666F Fancy Stack
定义一个塔是“好的”,仅当它从上往下第二层大于第一层,往后交替小于、大于上一层。且满足偶数层的数严格递增。
给定长度为 \(n\) 的序列 \(a\),问重排 \(a\) 能获得多少种好的塔。
这不是 DP 题吗。
先尝试设 DP 状态,简单推一下会发现难点在于去重,可能存在偶数层单调不降之类的情况。
那么不如直接钦定:两个塔的方案不同,仅当填入数的下标不同,最后再将相同数字内部排列的阶乘给除掉。
根据题目性质,偶数层递增,所以最后一个偶数层一定是前缀 \(\max\),可以以偶数为“阶段”,最后一层的数做“边界”。
具体地,设 \(dp_{i,j}\) 表示从上往下填了 \(2i\) 层,第 \(2i\) 层为 \(j\) 的方案数。
设 \(s_i\) 表示 \(a_j \in [1,i]\) 的数量,\(c_i\) 表示 \(a_j = i\) 的数量。
枚举上一层边界为 \(k\),则接下来奇数层可以填 \(s_{k-1}\) 个数,之前用了 \(2(i-1)-1\) 个,现在 \(j\) 有 \(c_j\) 种填法,所以方案数 \([ s_{k-1}-2(i-1)+1 ] \times dp_{i-1,k} \times c_j\)
T5 Yukicoder-2206 Popcount Sum 2
\(T\) 次询问 \(n,m\),求 \([1,2^n)\) 中 poocount 小于等于 \(m\) 的数字之和对 \(998244353\) 取模的值。
\(T, n, m \leq 2 \times 10^5\)。
单次询问是容易做到 \(O(m)\) 的。
枚举 popcount 再分别拆每一位的贡献:
这是一个组合数下指标求和的形式,多测可以用莫队优化到 \(O(n \sqrt{n})\)。
具体地设 \(S(n,m) = \sum\limits_{i=0}^{m} C(n,i)\),则有:
这样就可以分别 \(O(1)\) 地移动 \(n,m\) 指针。
\(\color{red}{\text{T6 CF1924D Balanced Subsequences}}\)
Day14【图论 1】
T1 CF1255C League of Leesins
对于一个长度为 \(n\) 的序列和 \(i \in [1,n-2]\),给定 \(a_i, a_{i+1}, a_{i+2}\),可能乱序,要求你还原序列,\(n \geq 5\)。
只出现一次的数在两端,接下来模拟即可,实现可以参考拓扑排序。
T2 洛谷 P9650 Escape Plan
给定一个 \(n\) 点 \(m\) 边的带权无向图,包含 \(k\) 个“出口”,你需要求出最坏情况下从 \(1\) 出发逃离到任意出口的最短时间。
当你走到 \(u\) 点时,与 \(u\) 点相邻的 \(d_u\) 条道路会随即封锁,封锁的道路不能同行。
反过来做,从 \(n\) 出发。
最短路联想到 dijkstra,但是封锁了 \(d_u\) 条,又要求最坏情况,所以把前 \(d_u\) 小的 dist 排掉,取第 \(d_u + 1\) 小的转移即可。
T3 洛谷 P5839 Moortal Cowmbat G
给定长度为 \(n\) 的由前 \(m\) 个小写字母构成的串 \(S\),你需要把它修改成字符串 \(T\),满足 \(T\) 中每一个极长的相同字符子串,长度都 \(\geq k\)。你每次可以修改一个位置,将字符 \(a\) 修改为 \(b\) 的代价是 \(w_{a,b}\),注意可能 \(a \to c \to b\) 比直接 \(a \to b\) 更优。
这哪是图论题啊,Floyd 也算吗?
不难想到先 Floyd 求出“直接转移”的最小代价,然后做 DP:设 \(f_{i,j}\) 表示前 \(i\) 个,最后一个被修改为 \(j\) 字符的最小代价。
转移考虑从 \(i-k\) 转移,或者继承 \(i-1\) 的字符,前缀和优化一下就是 \(O(nm^2)\)。
T4 Gym104857J Takeout Delivering
给定一个 \(n\) 点 \(m\) 边的带权无向图,定义一条路径 \(u \to v\) 的权值为最大值加次大值,求 \(1 \to n\) 的最小权路径权值。
考虑先用 dijkstra 求出 \(1 \to i\) 和 \(n \to i\) 路径上最大值的最小值,然后枚举最大值边 \((u, v, w)\),合并 \(1 \to u \to v \to n\) 三个部分,需要满足 \(w\) 是最大值。
T5 洛谷 P2934 Safe Travel G
给定一个 \(n\) 点 \(m\) 边的带权无向图,求从 \(1\) 到 \(2, 3, \dots, n\) 每个点,不经过最短路径中最后一条边时最短路是多少。
考虑建出最短路径树,则 \(x\) 的答案相当于禁用 \(x\) 的父亲后的最短路。
根据最短路的性质,需要仅用一条非树边代替这一条边,所以只能从 \(x\) 的子树通过非树边连到子树外。
考虑 \(x\) 子树选了一个点 \(u\),往外连 \((u,v,w)\),则 \(ans_x \leftarrow dis_u - dis_x + dis_v + w\)。
\(dis_x\) 确定,所以需要最小化 \(dis_u + dis_v + w\),这可以通过枚举所有边,跑树链剖分解决,复杂度双 \(\log\)。
可以用并查集优化到单 \(\log\)。
T6 洛谷 P6651 Chain
给定一个 \(n\) 点 \(m\) 边的有向无环图,不一定连通。\(q\) 次询问给定 \(k\) 个点,求删除这些点之后,原图中的极长链还剩下多少个(不计算新产生的极长链)。
极长链的定义是一条路径,满足开头入度为零,结尾出度为零。\(n \leq 2 \times 10^3, m \leq 2 \times 10^4, q \leq 5 \times 10^5, \sum k \leq 2 \times 10^6, k \leq 15\)。
部分分给的很足,考虑设 \(f_i\) 和 \(g_i\) 分别为入度为零走到 \(i\)、\(i\) 走到出度为零的方案数。
设 \(k=0\) 答案是 \(all\),即所有入度为零的 \(g\) 之和。
\(k=1\) 答案就是 \(all - f_u \times g_u\)。
\(k=2\) 直接容斥即可。
推广到 \(k \gt 2\) 也是容斥,对于所有可达点对 \(u \to v\) 建边,跑拓扑,边拓扑边容斥即可。
T7 CF875C National Property
给定一些字符串,其中字母用数字表示,并且初始是小写的。你可以把一些小写字母改成大写,但同时你要把所有同种字母全部改成大写。
问是否能经过一些操作使得最终的字符串序列满足按字典序升序排列。如果能,则需要输出方案。
升序排序等价于相邻的两个字符串有序,考虑先求出相邻两个字符串的第一个失配位置,设前一字符串这个位置为 \(x\),后一字符串这个位置为 \(y\)。
- 若 \(x \lt y\):
- 当 \(x\) 选小写时,\(y\) 必须选大写。
- 当 \(y\) 选大写时,\(x\) 必须选小写。
- 若 \(x \gt y\):
- 则 \(x\) 必须选大写,\(y\) 必须选小写。
不难注意到这是 2-SAT 的形式,注意构造方案是按照 SCC 编号逆拓扑序。
T8 洛谷 P6062 Muddy Fields G
一个 \(n \times m\) 的牧场,每个点可以是泥地或者草地。你需要用若干 \(1 \times x\) 的木板覆盖所有泥地,不能覆盖到草地,求最少木板数量。\(1 \leq n, m \leq 50\)。
给每一个极长的横竖泥地连续段编号,对于泥地 \((x,y)\),将它对应的横竖连续段连边。
建出来的是二分图,答案相当于最小点覆盖,即二分图最大匹配。
T9 HDU 7488 猫咪们狂欢
有两棵 \(n\) 个点的树,边有边权,给定 \(k\) 个关键点 \(a_1 \to a_k\),你需要将两棵树中编号为 \(a_i\) 点染黑恰好一个。
染色方案的权值定义为连接两个黑点的边权和,最大化这个值。
似乎不难想到网络流?然后拼命想二分图网络流,没救了。
事实上是三层图网络流,类似于最大权闭合子图。安利 网络流 23 题。
左右两层分别是两棵树的边,中间一层是点。树边连点是 INF,树边连源汇点是对应边权。
用总边权和减去最小割即可。
T10 CF818G Four Melodies
给定一个长度为 \(n\) 的序列 \(a\),需要从中选取 \(4\) 个非空且互不相交的子序列,这些子序列满足如下条件:
任意两个相邻元素要么相差 \(1\),要么对 \(7\) 取模相等。
求子序列最大长度和。
比较容易想到 \(O(n^5)\) 的 DP 做法。
比较难想到网络流。
每个点往它后一个可以匹配的点连一条边,建立超级源点往源点连容量为 \(4\),求最大费用流。
边数是高贵的 \(O(n^2)\),考虑优化。
一个正常的想法是每个点连它后面第一个匹配的点,但是会被 hack:1 9 8 7 15 6
,形如这样的数据可能会选 1 8 15
和 7 6
,但更优的选择是 1 15
和 9 8 7 6
。这个例子不是很对,毕竟可以选四个子序列,但是大致是这个意思。
考虑直接给模 \(7\) 同余的点额外开一整条路,这样可以通过这条路到后缀所有同余点;对于 \(a_i\) 相同的同理。
那么边数就变成 \(O(n)\) 了,注意不能有环,所以每个点要指向线路上它对应点的后一个点,而不是它对应的点。
闲话:直接连前五个合法的也能直接冲过去,可能比较难卡。
Day15【图论 2】
T1 CF1679D Toss a Coin to Your Graph...
给定一个有向图,每个点有点权,你可以任选起点开始走 \(k\) 步,求走过的最大权值最小是多少,可能存在无解。\(k \leq 10^{18}\)。
看到最大值最小果断二分,然后把 \(\leq mid\) 的点加进去看是否能走 \(k\) 步。
如果有环则一定可行,如果无环说明是个 DAG,可以拓扑排序求出最长路。
这两件事可以同时做,具体地,如果拓扑排序结束后还有节点未入队,则说明有环。
复杂度 \(O(n \log n)\)。
T2 CF1213F Unstable String Sort
你需要构造一个长度为 \(n\),由前 \(k\) 个小写字母组成的字符串,使得按照给定排列 \(p, q\) 的顺序读字符串,都是单调不降的。
先建边 \(p_i \to p_{i+1}, q_i \to q_{i+1}\),则一个 SCC 内的位置字符必须相同。
然后缩点形成一张 DAG,检查最长路是否 \(\geq k\) 判断有无解。
输出方案按照最长路即可。
T3 CF2000G Call During the Journey
给定一张 \(n\) 个城市的交通路线图,有 \(m\) 条边,每条边有人行道和公交车两种通行方式,给定它们分别所需的时间。
你需要从 \(1\) 出发,且在 \([L,R]\) 时间段内必须走人行道,在不晚于 \(t_0\) 时刻到达 \(n\) 点,求你最晚几点出发。
二分转判定性问题。
然后把从 \(1\) 通过公交车在 \([mid,L]\) 时间内能走到的点拿出来(最短路),扔到人行道上继续跑 dijkstra。
接着从 \(n\) 反向跑一边公交车 dijk 求出每个点到 \(n\) 的最短路。
两者拼在一起判断 \(\leq t_0\) 即可。
T4 洛谷 P2416 泡芙
一张无向图,边权为 \(0\) 或 \(1\),\(q\) 次询问 \(u \to v\) 是否存在一条路径,使得路径上至少有一条 \(1\) 边。走过的边不能再走。
由于边只能走一次,不妨先边双缩点,这样路径上经过的边双可以转一圈回来。
将边双内是否有 \(1\) 的边刻画为点权,缩完点是一棵树,树上边刻画为树边权。
则相当于问缩点后 \(u \to v\) 路上点和边是否存在 \(1\),这可以树上前缀和轻松维护,复杂度 \(O(q \log n)\)。
T5 洛谷 P11907 F. 恐怖的黑色魔物
一个三维空间中有若干关键点,定义一个点的“恐怖距离”为距离它最近的关键点的三维曼哈顿距离。
若干次询问,从 \((a,b,c)\) 走到 \((x,y,z)\),请最大化路径上最小恐怖距离。
首先不难多源 bfs 求出每个点的恐怖距离。
然后以恐怖距离为点权,直接连边做点权多叉重构树,一次查询相当于求重构树上 LCA 的点权,这是简单的。
T6 CF325C Monsters and Diamonds
有 \(n\) 种编号为 \([1,n]\) 的基本元素,和一种特殊元素 \(-1\)。给定 \(m\) 条规则,形如:\(x, c, a_1, a_2, \dots, a_c\),表示 \(x\) 可以通过此操作分裂为 \(a\) 中每个元素各一个(\(a\) 中元素可能重复)。
对每个基本元素求出,如果最开始你只有一个这种元素,你能通过操作分裂出的最少和最多特殊元素是多少。
保证每种操作至少分裂出一个特殊元素,若操作无法停止输出-1 -1
,若你可以获得 \(\infty\) 特殊元素且可以随时停止则最大值输出-2
,否则输出最小最大值。
一个比较聪明的思考方法是:把规则看作虚点 \(new\),则操作连边 \(x \to new \to a\)。
不妨将 \(-1\) 的数量看作点权,边有边权(同种元素分裂出的数量)。
建反图,从入度为 \(0\) 的点为源点跑 dijkstra,原点和虚点转移不同,需要分类讨论。
- 原点需要对任意一个前驱虚点取 \(\min\)(反图上)。
- 虚点需要将所有前驱原点的贡献都加起来。
观察到虚点需要等所有前驱原点都转移完才能入队,所以这东西很像 toposort。
那么不妨先将这个算法命名为 dijksort 或 topostra(?)。
跑完 dijksort 之后还没有入队的点,说明它在一个环内,且它走不出去(即无法停止操作),则答案为 -1 -1
。
否则我们跑 dijkstra 刚好求出了最小值答案。
然后将没入队的点删掉,重新建一次反图,这次就不用考虑 -1 -1
的情况了,难点是 -2
的判定。
我们发现剩下的点虽然可能在环里,但是它可以自由决定什么时候走出环,这样的点最大值就是 -2
。
因此将新的反图跑 toposort,直接做取 \(\max\) 的 DP,最后还没有入队的说明在环内,最大值为 -2
,否则为 DP 值。
Day16【放假,好耶】
Day17【树上问题 1】
T1 CF1336A Linova and Kingdom
给定一棵 \(n\) 个点的树,需要选 \(k\) 个点染黑,最大化所有黑点到 \(1\) 号点路径上白点数量的总和。
贪心地让黑点在最外圈,设一个点的权值为 \((dep_u - 1) \times sz_u\),即整个子树染黑的权值。
然后从下往上做类似拓扑排序的事情,用大根堆维护父子权值差最优的节点。
T2 洛谷 P5536 核心城市
给定一棵 \(n\) 个点的树,要求选 \(k\) 个联通的点,使得没有被选的点到这个连通块的距离的最大值最小。
和上一题很像,正难则反,从周围往中间拓扑排序,删除 \(n-k\) 个点。
T3 CF771C Bear and Tree Jumps
给定一棵 \(n\) 个点的树,求 \(\sum\limits_{i=1}^{n} \sum\limits_{j=i+1}^{n} \lceil \frac{dist(i,j)}{k} \rceil\),满足 \(k \leq 5\)。
设 \(cnt_{u,i}\) 表示 \(u\) 子树相对深度 \(\bmod k = i\) 的节点数量,\(dis_{u,i}\) 表示这些点到 \(u\) 的贡献和。
转移是简单的,重点在于合并路径。
- 第一种情况是 \(u\) 为 \(v\) 的祖先,贡献是 \(dis\)。
- 第二种可以枚举 \(k_1, k_2\) 表示两边 \(\bmod k\) 的值,然后再计算贡献。
复杂度 \(O(n k^2)\)。
T4 CF2033G Sakurako and Chefir
给定一棵 \(n\) 个节点的树,\(q\) 次询问求 \(u\) 点 \(k\) 级祖先的子树内距离 \(u\) 最远的点距离是多少。
一个比较直接的做法是记 \(mx_u\) 为 \(u\) 往下最多走多少步。
则枚举 \(lca\) 为 \(pa\),贡献为 \(\max \{ dep_u - dep_{pa} + mx_{pa} + 2 \} = \max \{ mx_{pa} - dep_{pa} \} + dep_u + 2\),需要维护 \(\max\) 里面的这个东西。
记 \(val_u\) 为 \(u\) 的兄弟中 \(mx\) 的最大值,这样可以除去 \(u\) 子树信息。
然后 \(k\) 级祖先直接倍增就行了。
T5 洛谷 P4949 最短距离
给定一棵 \(n\) 个点的基环树,\(q\) 次操作两种类型:单边修改权值、查询 \(x \to y\) 最短距离。
先随便挑出环上一条边 \((u, v, w)\),然后对剩余的树直接做树链剖分,查询特殊判一下 \(x \to u \to v \to y\) 和 \(x \to v \to u \to y\) 即可。
这是我第一次树链剖分写树状数组。
T6 CF1709E XOR Tree
给定一棵 \(n\) 个节点的树,点有点权 \(a_u\),你需要修改任意点的点权为任意正整数,使得树上不存在异或为 \(0\) 的路径。问最少操作多少个点。
先做树上前缀和 \(d\),则异或为 \(0\) 的路径需要满足:\(d_u \oplus d_v = a_{lca}\)。
考虑修改 \(lca\) 的点权:\(\displaystyle (d_u \oplus a_{lca} \oplus new) \oplus (d_v \oplus a_{lca} \oplus new) =? a_{lca} \oplus a_{lca} new\)。
化简得:\(d_u \oplus d_v =? new\),显然 \(new\) 一定可以取到一个不为 \(d_u \oplus d_v\) 的数。
因此可以在点 \(u\) 操作使得 \(u\) 子树不存在以 \(u\) 为 \(lca\) 的路径。
然后从下往上模拟这个过程,由于涉及合并子树集合,需要使用 Dsu On Tree,可以用 set 维护集合,复杂度为 \(O(n \log^2 n)\)。
T7 CF1794E Labeling the Tree with Distances
给定一棵 \(n\) 个点的树和一个长度为 \(n-1\) 的序列 \(a\),你需要把 \(a\) 中每个数分给树上每个点作为点权,没有被分配 \(a\) 到的点你可以任意钦定点权。
如果存在一种分配方式使得点权恰好等价于以 \(x\) 点为根的深度,那么 \(x\) 点是“好的”,求有多少个点是好的。
考虑不存在任意钦定点权这件事,怎么匹配。
不难想到直接哈希,记深度为 \(i\) 的点有 \(c\) 个,则哈希的第 \(i\) 位为 \(c\),由于涉及进位需要强行钦定 \(base \gt n\)。
然后需要判断每个点是否是好的,考虑换根,发现深度在 \(base\) 进制下会整体位移,所以是好做的,可以 \(O(1)\) 转移到儿子的哈希值。
最后再考虑任意钦定点权,其实点权最多只有 \([0,n)\) 共 \(n\) 种,所以暴力开个 map 存即可。
Warning:本题卡自然溢出、常见模数底数哈希等,所以我写了随机底数模数十哈希硬冲过去了。
T8 CF914E Palindromes in a Tree
给定一棵树,树上每个点有一个 \([a,t]\) 的小写字母,对于每个点,求有多少条经过它的路径,能通过重排列字符变成回文串。
由于可以重排列,就只和字符出现的奇偶性相关,由于最多 \(20\) 个字母,这可以状压。
合法的路径相当于状压为 \(0\) 或 \(2^k\)。
路径计数考虑点分治,但是直接记录每个状态有哪些点复杂度会上升到高贵的 \(O(n^2)\)。
记录点是为了不算重,不妨钦定可以算重再除以每个点被重复算几次。
这样只需要对每个子树求子树外的状态出现次数即可,只有根会有算重的问题,跨过它的会被算两遍,从它往下延伸的会被算一遍,前者除以二即可。
T9 CF1016F Road Projects
给定一棵 \(n\) 个节点的树,\(q\) 次询问一个边权 \(x\),你需要在不相邻的点 \(u,v\) 之间连边权为 \(x\) 的边,使得 \(1 \to n\) 的最短路尽量大。
\(n,q \leq 3 \times 10^5\)。
一个简单的想法是暴力枚举 \(u,v\),然后看形成的环走哪一边更短。但这样复杂度无法优化。
由于起点终点是固定的,所以在原树上 \(1 \to n\) 路径也固定,不妨把这条链先扯出来。
链上每个点可能挂一棵子树,只要有一个子树大小 \(\geq 3\) 就可以在子树内连边,这不影响答案。(显然到子树内转一圈再出来是不优的)
然后问题就变成子树之间连边,为了使答案最大肯定选最深的点连边,记最大深度为 \(a_i\),链上边权前缀和为 \(s_i\)。
则需要找到:\(i \lt j\),若 \(i+1=j\) 需额外满足至少有一个子树大小 \(\gt 1\)。最大化 \(a_i + a_j - (s_j - s_i) + x\)。
这个式子和 \(x\) 无关,从后往前扫一遍维护 \(a_j - s_j\) 的最大值次大值即可。
复杂度 \(O(n)\),感觉并没有 *2600。
\(\color{red}{\text{T10 CF1479D Odd Mineral Resource}}\)
Day18【树上问题 2】
T1 洛谷 P8578 So What Do We Do Now?
给定一棵树,你需要给每个点赋点权,使得点权构成一个排列。设 \(f_i\) 为 \(i\) 子树内点权的极差,你需要最小化 \(\sum\limits_{i=1}^{n} f_i\)。
Cocoly 怎么会出这么抽象的题。
子树极差最少也得是子树大小减一,不难想到输出 dfs 序即可。
T2 CF1244D Paint the Tree
给定一棵 \(n\) 个点的树,需要给每个点涂上三种颜色之一,第 \(i\) 个点涂成第 \(j\) 种颜色的代价是 \(c_{j,i}\),你需要求出最少的涂色代价,使得树上任意连续的三个点颜色不同。输出方案。
显然如果不是链则无解。
否则可以枚举最开始三个怎么涂色,后面递推往后涂,输出方案是简单的。
T3 CF1790F Timofey and Black-White Tree
一棵 \(n\) 个点的树初始只有一个点为黑,其它都为白,\(n-1\) 次操作将一个节点染黑,求黑色最近点对距离。
诈骗题!经过 \(x\) 次操作后答案一定 \(\leq \frac{n}{x}\)。
基于这个结论有个复杂度正确的暴力:每次从染黑的点开始 bfs 更新最近距离,如果当前点深度超过它的最近距离,或者超过全局答案则不用继续拓展。
复杂度分析:
- 前 \(\sqrt{n}\) 次操作拉满了也只有 \(O(n \sqrt{n})\)。
- \(\sqrt{n}\) 次之后 dist 不会超过 \(\sqrt{n}\),每次更新 dist 至少 \(-1\),所以每个节点最多被更新 \(\sqrt{n}\) 次,复杂度 \(O(n \sqrt{n})\)。
T4 Gym 102012G Rikka with Intersections of Paths
给定一棵 \(n\) 点树和树上 \(m\) 条路径,求选出 \(k\) 条路径使得它们覆盖点的交集不为空的方案数。
不难想到树上差分求出每个点被覆盖了几次,设覆盖了 \(d1_i\) 次就 \(ans \leftarrow ans + \binom{d1_i}{k}\),但显然是错误的。
因为如果一条路径覆盖相邻两个点就会被算两次。
考虑“点减边”套路,设 \(i\) 和父亲的连边被覆盖了 \(d2_i\) 次,则 \(ans \leftarrow ans - \binom{d2_i}{k}\),这样容斥掉就不会有问题了。
T5 CF1842F Tenzing and Tree
给定一棵 \(n\) 个点的树,你要把 \(k\) 个点染成黑色。一条边的权值定义为它左右两边黑点数量之差的绝对值,你需要对所有 \(k \in [0, n]\) 求最大边权和。\(n \leq 5000\)。
对于一条边,设它两边更大的是 \(mx\),更小的是 \(mn\),则它的权值为 \(mx - mn = (mx+mn) - 2mn = k - 2mn\),所以需要最小化 \(mn\) 之和。
不妨枚举黑点的重心当作根 \(root\),则每个黑点对 \(mn\) 的贡献是它的 \(dep\),选深度最小的 \(k\) 个点即可。
枚举黑点重心是因为不同 \(k\) 对应的染黑方案重心可能不同。
T6 CF1149C Tree Generator™
我们用括号序列表示一棵树:
(
表示新建一个子节点,)
表示返回到父亲,则 \(n\) 个点的树对应的括号序列长为 \(2(n-1)\)。
给定你这么一个括号序列,\(q\) 次操作交换两个不相同的括号,问每次操作后树的直径。
考虑树的直径 \((u,v)\) 在 \(\text{lca}(u,v)\) 处统计,那么就相当于枚举 \(\text{lca}\) 求它子树中深度的最大值和次大值。
如果把 (
看作 \(1\),)
看作 \(-1\),画出折线图,则相当于枚举下标,求左右的最大值,那么贡献就是 \(\text{lmax+p_i+rmax}\)。
考虑线段树维护,每个位置记录 \(\max, \min, \text{lmax-2min}, \text{rmax-2min}, \text{lmax+rmax-2min}\)。
类似于 D3T5 文文的摄影布置维护,这题是区间加减,写个懒标记给影响的元素对应加减即可。
Day19【数学】
T1 CF947A Primal Sport
对于一个 \(\geq 2\) 的正整数 \(x\),称一次“变换”为:选一个 \(\leq x\) 的质数 \(p\),将 \(x\) 变成 \(\geq x\) 的最小 \(p\) 的倍数。
给你经过两次变换后的一个数 \(x_2\),请你求出最小的 \(x_0\) 使得它能通过两次变换变成 \(x_2\)。
对于一个质数 \(p\),只有 \(((i-1)p,ip]\) 的数可以转移到 \(ip\),那么对于 \(x\) 肯定希望找到它的最大质因数才能尽可能让左边界更偏左。
先找 \(x_2\) 的最大质因子,再将区间内的每个点都找一下最大质因子即可更新左边界。
T2 CF1499D The Number of Pairs
给定三个正整数 \(c,d,x\),求出 \(c \times \text{lcm}(a,b) - d \times \gcd(a,b) = x\) 的二元组 \((a,b)\) 数量。
设 \(\gcd(a,b) = t, \text{lcm}(a,b) = t \times pq\),保证 \(\gcd(p,q) = 1\),则题目限制可以写成:\(\displaystyle c \times t \times pq - d \times t = x\)。
经过一波化简可以得到:\(\displaystyle pq = \frac{\frac{x}{t} + d}{c}\)。
枚举 \(t\),看 \(\frac{x}{t} + d\) 是否是 \(c\) 的倍数,如果是则这个整体的相同质因子不能被分别分配到 \(p\) 和 \(q\),所以一个质因子只能分配给其一。
设 \(\frac{\frac{x}{t} + d}{c}\) 有 \(k\) 个质因子,则有 \(2^k\) 种分配方案。
可以线性筛顺便求出质因子数量。
T3 洛谷 P12021 面包题
从 \(1 \sim n\) 的自然数中选出若干个数(可以不选),满足以下条件:若选择了 \(x\),则不能选择 \(kx\)。
求总共有多少种选法(不考虑选择顺序)。
首先不难想到 \(i \to ki\) 连边,会形成若干条链,则你不能同时选择链上相邻两点。
考虑对于一条长度为 \(l\) 的链,怎么求方案数。
设 \(f_{i,0/1}\) 表示链上前 \(i\) 个点,第 \(i\) 个没选 / 选了,的方案数。
则有:\(f_{i,0} = f_{i-1,0} + f_{i-1,1}, f_{i,1} = f_{i-1,0}\),把它改一个形式其实 \(f_{i,0}\) 就是斐波那契数列。
然后我写了一个比较笨的方法,直接整除分块去整链的数量,但是它 T 飞了。
事实上可以用容斥解决,求出长度至少为 \(l\) 的链的数量,链头不能是 \(k\) 的倍数。
那么长度至少为 \(1\) 的链有 \(n - \lfloor \frac{n}{k} \rfloor\) 条,长度至少为 \(2\) 的链有 \(\lfloor \frac{n}{k} \rfloor - \lfloor \frac{\lfloor \frac{n}{k} \rfloor}{k} \rfloor\) 条……倒着就做完了。
T4 洛谷 P12952 Intruder Outsmarting
有 \(w\) 个模 \(n\) 意义下的数,每次操作你可以把一个位置 \(+d\) 或 \(-d\),问最少要多少次操作将序列变成回文串。
从两边往中间做,看 \(x,y\) 两个数要经过几次操作才能相等。
这不就是个同余方程吗,exgcd 秒了。
T5 洛谷 P6583 回首过去
给定正整数 \(n\),求出有序整数对 \((x,y)\) 的个数,满足 \(1\le x,y\le n\) 且 \(\frac{x}{y}\) 可以表示为十进制有限小数。
等价于计数 \(\frac{y}{\gcd(x,y)} = 2^a 5^b\),移项可得 \(\gcd(x,y) = \frac{y}{2^a 5^b}\)。
不妨枚举 \(y\),把 \(2,5\) 因子全部先除掉,设结果为 \(p\),则符合条件的 \(x\) 有 \(\lfloor \frac{n}{p} \rfloor\) 个。这样可以做到 \(O(n \log n)\) 获得 80pts。
枚举 \(y\) 很难优化,换个角度枚举 \(t=2^a 5^b\)。
直接做的话复杂度爆表,但是不妨先处理出整除分块的若干个区间,单次查询 \(t\) 可以二分在区间中的位置。
对于不含 \(2,5\) 因子,可以容斥。
T6 CodeChef Little Elephant and Colored Coins
有 \(n\) 个硬币,每个硬币有价值 \(v_i\) 和颜色 \(c_i\),\(q\) 次询问你需要求出恰好拼凑出 \(S\) 价值用到最多的颜色数。
\(n \leq 30, v_i \leq 2 \times 10^5, c_i \leq 10^9, q \leq 2 \times 10^5, S \leq 10^{18}\)。
\(S\) 太大了显然没法直接背包,但是 \(v\) 相对较小,考虑和其有关的做法。
同余最短路。
假设没有颜色这个限制,单纯问你能不能拼凑出 \(S\)。设 \(dp_i\) 表示价值总和 \(\mod v_1=i\) 的情况下,最小的价值总和是多少。
那么只要满足 \(dp_S \leq S\),就可以通过不断补充 \(v_1\) 使它到达 \(S\)。
问题在于如何转移,你会发现 \(i \to (i + v) \bmod v_1\) 它形成了若干个环,只要顺着环绕两圈更新就可以。
现在考虑加入颜色这个限制,把相同颜色的分到一组,设 \(f_{i,j}\) 表示总共选了 \(i\) 种颜色,总和取模后为 \(j\),最小的总和是多少。
每次加入一种颜色内的所有硬币并转移,然后把转移后的绕着环跑两圈即可。
T7 洛谷 P2150 寿司晚宴
需要将 \(2 \sim n\) 的数分给两个人,可以存在数不分给任何人,使得不存在分给了第一个人数字 \(x\),第二个人数字 \(y\),且 \(\gcd(x,y) \not= 1\)。\(n \leq 500\)。
这哪是数学啊,分明是 DP。
对于 \(n \leq 30\) 是一个裸的状压 DP,然后考虑发掘性质。
每个数至多只有一个 \(\gt \sqrt{n}\) 的质因子,我们称它为“大质因子”。其它的则成为“小质因子”。
容易发现小质因子只有 \(8\) 个,然后状压!
先将大质因数相同的数分到一组,一组内的数只能分给一个人。
设 \(f_{S,T}\) 表示分给第一个人的小质因子集合为 \(S\),第二个人为 \(T\) 的方案数,然后我们以组为单位转移。
设 \(g_{S,T}\) 表示前 \(i\) 组,这一组全给第一个人的方案数,状态类似,且 \(g\) 是对称的。
容斥一下 \(f_{S,T} = g_{S,T} + g_{T,S} - f_{S,T}\),因为都不给的状态被算了两次。
T8 ABC335G Discrete Logarithm Problems
给定质数 \(P\) 和 \(n\) 个数 \(a_i\),问有多少对 \((i,j)\) 满足存在正整数 \(k\) 使得 \(a_i^k \equiv a_j \pmod P\)。
\(P \leq 10^{13}, n \leq 2 \times 10^5\)。
很(不)牛的题,卡在了判断是否在同一个环上。
不难想到与原根和阶相关,不妨先求出 \(b_i\) 表示 \(a_i\) 的阶。
转化为 \(b_j | b_i\),由于 \(b\) 最多只有约 \(10^4\) 种取值,可以存在桶里暴力。
总复杂度 \(O(n \times \log^2 P + d(P)^2)\)。
T9 CF645F Cowslip Collections
给定一个长度为 \(n\) 的序列和参数 \(k\),\(q\) 次操作,每次在序列末尾加入一个元素 \(x\)。
每次操作后求序列 所有大小为 \(k\) 的子序列的 \(\gcd\) 之和。
反着做,枚举 \(i\) 的所有倍数,设 \(i\) 在序列有 \(cnt_i\) 个倍数,则 \(x | \gcd\) 的方案数为 \(g_x = \binom{cnt_i}{k}\)。
设 \(f_x\) 表示 \(x = \gcd\) 的方案数,那么有 \(g_n = \sum\limits_{n | d} g_d\)。
莫反可得:\(f_n = \sum\limits_{n | d} \mu(\frac{d}{n}) g(d)\)。
由于 \(ans = \sum\limits_n f_n \times n\),有:
经典交换枚举顺序:
事实上 \(\sum\limits_{n | d} n \mu(\frac{d}{n}) = \varphi(n)\),于是:
预处理 \(\varphi\),每次加入一个数更新它因数的 \(cnt\),将对应的贡献修改即可。
T10 CF1515G Phoenix and Odometers
给定一张 \(n\) 个点 \(m\) 条边的有向图,有边权,进行 \(q\) 次询问(\(n,m,q \leq 2 \times 10^5\),边权为不超过 \(10^9\) 的正整数)。
每次询问给定三个参数 \(v,s,t(0\leq s \lt \leq 10^9)\),你需要回答是否存在一条起点终点均为 \(v\) 的路径,满足 路径长 \(+ s \equiv 0 \pmod t\)。
首先一个点肯定不能走出 SCC,否则就回不来了。
猜想这和 SCC 内的环有关。
设 SCC 中环的大小分别为 \(x_1,x_2,\dots,x_n\),存在 \(k_1x_1 + k_2x_2 + \dots + k_nx_n \equiv s \pmod t\) 的条件为 \(s\) 是 \(\gcd(x_1,x_2,\dots,x_n)\) 的倍数(详见裴蜀定理)。
考虑到有很多 \(x_i\) 是不必要的。观察到任意一个环均可以被过 dfs 树上的环表示。
所以在 dfs 树上直接做,求 gcd 即可。
Day20【被打成退役选手了】
QwQ.