IOI2020国家集训队作业 Part 1
开坑!开坑!开坑!虐身虐心警告。
CF504E Misha and LCP on Tree
- 给定一棵树,每个节点有一个小写字母。
- \(m\) 次询问,求路径 \((a,b)\) 和 \((c,d)\) 的 LCP。
- \(n\leq 3\times 10^5,m\leq 10^6\)。
直接 Hash,不要傻傻的写成两只 \(\log\),更不要直接套个二分 + 树剖三只 \(\log\)。
直接套用树剖结构,提取出 $\log $ 个区间,先区间相消,如果消不了了就在区间里二分,小常数单 \(\log\)。
CF505E Mr. Kitayuta vs. Bamboos
- 给定 \(n\) 个数 \(h_i\),进行 \(m\) 轮操作,每次可以选择 \(k\) 个 \(h_i\) 进行 \(h_i\gets \max(h_i-p,0)\)。
- 每轮操作后,会有 \(h_i\gets h_i+a_i\)。
- 最小化最终的 \(\max h_i\)。
- \(n\leq 10^5,m\leq 5\times 10^3,k\leq 10\)。
二分答案改为每次给 \(k\) 个数加,逆向看是否能倒回 \(m\) 轮。
不要分步模拟这个过程,因为加减均有交换律,所以当直接枚举轮数,每次给“最紧急”的 \(k\) 个加,直接用堆维护。
如果中途都没了那就没了,否则最后还要让每个数能达到初始值。
CF506E Mr. Kitayuta's Gift
- 给定字符串 \(s\),求在 \(s\) 中插入恰好 \(n\) 个小写字符使其变为回文串的方案数。
- \(|s|\leq 200,n\leq 10^9\)。
老神仙了。
第一步是要想到一个关于 \(m=|s|\) 的多项式的算法,也算是关键步骤了。
因为是回文串,所以两端应当一起考虑,先假设 \(n+m\) 为偶数。
令 \(f(i,l,r)\) 表示填了首尾 \(i\) 对字符,前后尽量和原串匹配后,还剩下区间 \([l,r]\) 的方案数。
设 \(g(i)\) 表示用 \(i\) 对首尾能完全匹配的方案数,答案就是 \(g(\frac{n+m}{2})\)。
转移需要讨论一下:
- \(s_l=s_r\):
- 若 \(r-l\leq 1\),\(g(i+1)\gets f(i,l,r)\) 和 \(f(i+1,l,r)\gets 25\times f(i,l,r)\)。
- 若 \(r-l>1\),\(f(i+1,l+1,r-1)\gets f(i,l,r)\) 和 \(f(i+1,l,r)\gets 25\times f(i,l,r)\)。
- \(s_l\neq s_r\):
- \(f(i+1,l+1,r)\gets f(i,l,r)\)。
- \(f(i+1,l,r-1)\gets f(i,l,r)\)。
- \(f(i+1,l,r)\gets 24\times f(i,l,r)\)。
- 对 \(g\):\(g(i+1)\gets 26\times g(i)\)。
为了去除 \(n\) 的影响,可以强行用矩阵加速这个 \(O(m^2)\) 个状态的递推,复杂度为 \(O(m^6\log n)\)。
发现这类转移能很好的表达到一张图上(来自官方题解):
这是 \(\texttt{abaac}\) 的转移过程,红色和绿色分别对应 \(s_l\neq s_r\) 和 \(s_l=s_r\) 两种转移。
观察到上述转移中,红色点有 \(24\) 的自环,绿色有 \(25\),蓝色对应的 \(g\) 则有全图唯一的 \(26\) 的自环。
同时不难发现,非自环边的权值都是 \(1\),并且只能从绿色点到达目标点。
最终答案等价于从右上角出发,经过恰好 \((n+m)/2\) 步到达目标点的路径权值之和,路径权值是途径权值的乘积。
将图片可视化之后,很快能发现,路径的具体形态不被关心,而是只关心路径上红色点(\(24\) 的自环)和绿色点(\(25\) 的自环)的个数。
而且能够发现,若一条路径有 \(x\) 个红色点,就一定有 \(\lceil\dfrac{m-x}{2}\rceil\) 个绿色点。
因为红色点的出边每次将区间长度 \(-1\),而绿色则大部分情况下 \(-2\),只在转移到终点时有特殊,所以要上取整。
综上,所有红色点个数相同的路径是本质相同的,可以利用这一点加速转移!
分别建立如上面第一张图的转移路径,每张只有 \(O(m)\) 个点,而本质不同的路径也只有 \(O(m)\) 个,直接矩阵转移就是 \(O(m^4\log n)\) 的。
当然要记搜预处理出 \(f(i)\) 表示途径恰好 \(i\) 个红色点的转移路径数。
同时实际上发现这样做还是太傻了,可以直接上面一排红色点,下面一排绿色点,再在两排之间对应连边就好了,如上面的第二张图。
复杂度变为 \(O(m^3\log n)\),而且转移形式是 DAG,所以转移矩阵是上三角矩阵,所以可以减少很多常数。
对于 \(n+m\) 为奇数的情况,把它当作 \(n+m+1\) 处理,再容斥掉一些情况即可。
需要容斥掉最后一次匹配不能填上当个字符的方案,发现就是只转移 \(r-l=1,g(i+1)\gets f(i,l,r)\) 且最终 \(g\) 没有多余匹配的方案。
无非就是把 \(f\) 重新计算,再把终点的自环去掉,再跑一遍即可。
CF512D Fox And Travelling
- 给定 \(n\) 个点 \(m\) 条边的无向图,一个点只有当它度数 \(\leq 1\) 时才能被删除。
- 对于每个 \(k\in[0,n]\),求有序删除 \(k\) 个节点的方案数。
- \(n\leq 100,m\leq \dfrac{n(n-1)}{2}\)。
发现对于一个环它永远无法被选择,需要考虑的只有有根树和无根树两种情况。
均可类似的使用树形 DP 解决,对于有根树的计算需要去重,钦定/换根/直接除法 都是不错的选择。
CF516D Drazil and Morning Exercise
- 给定一棵带边权的树,定义 \(f_x=\max_{i=1}^n \text{dis}(x,i)\)。
- \(q\) 次询问最大的满足 \(\max _{x\in s} f_x-\min _{x\in s} f_x\leq l\) 的连通块 \(s\) 的大小。
- \(n\leq 10^5,q\leq 50\)。
把直径提取处理画成一排,把子树挂在上面,十分形象。
发现每棵子树的 \(f\) 值都是随深度严格递增的,这一点非常有用。
根据连通块是否跨子树讨论,只在一个子树内非常好统计。否则考虑枚举连通块中的 \(\min\),它一定是某棵子树的根!
然后处理出这个根能扩展到的区间,因为递增性保证连通性,所以相当于二位数点,离线树状数组即可。
实际上 std 更简单,考虑双指针滑动一下,从大到小就不会影响连通性了,只是单点取消的时候在对应连通块 \(-1\)。
CF516E Drazil and His Happy Friends
- 有标号为 \([0,n)\) 的 \(n\) 个黑点和标号为 \([0,m)\) 的 \(m\) 个白点。
- 初始有 \(B\) 个黑点和 \(G\) 个白点是快乐的,其他都是不快乐的。
- 在第 \(i\) 天,编号为 \(i\bmod n\) 的黑点会和 \(j\bmod m\) 的白点联会,如果有任意一个快乐,那么联会后两者都会快乐。
- 求至少多少天能使所有人快乐,或者判定不可能。
- \(n,m\leq 10^9,B,G\leq 10^5\)。
妙妙数论题。
只想到了只有 \((n,m)|\text{dis}\) 的点对会在某个时刻联会。
实际上考虑直接按 \(\bmod d\) 分类,分别考虑答案,对于 \(\bmod d=i\) 的类,最终的实际贡献是 \(d\times \text{ans}+i\)。
对于一类,如果初始没有开心的人就无解,否则一定有解。注意若 \(d>B+G\) 就一定无解,看似没用但实际保证了 \(d\) 是 \(10^5\) 级别的。
不妨设 \(n>m\),首先特判掉在前 \(m\) 步就完成的情况。
否则只需要考虑左边 \(n\) 个点的开心时间,因为这样倒退 \(m\) 步,要么感染右边,要么被右边感染。
把右边初始开心的都对称到左边来,发现若左边 \(i\) 初始开心,他就会先感染右边的 \(i\),并借此感染到左边的 \((i+m)\bmod n\)。
那是否能视为**左边的 \(i\) 能感染左边的 \((i+m)\bmod n\) **呢!
发现可以建图:
- 对于初始开心的点 \(i\),连边 \((s,i,i)\)。
- 对于任意点 \(i\),连边 \((i,(i+m)\bmod n,m)\)。
跑最短路,最大值就是答案,可惜总点数过大,不能接受。
但是不难发现,第二种边将图连成了一个大环,而如果 \(i\) 和 \((i+m)\bmod n\) 这两个相邻节点初始均不开心,那么后者一定被前者感染。
换句话说前者就是不重要的,只需要保留初始开心的点,和它们在环上的前驱即可,这是 \(O(B)\) 个的,就有保证了。
连边的时候有些技巧,就是对每个初始开心的点都建两个点,\(a_i\) 表示自己,\(b_i\) 表示自己的前驱。
然后连边 \((s,a_i,i),(b_i,a_i,m)\),同时还需要找每个点在环上的相邻点,设 \(x\) 表示最小的满足 \(mx\equiv 1\pmod n\) 的值(可以用一次 exgcd 求出)。
那么两个点 \(c,d(c>d)\) 的环上距离就是 \((d-c)\times x\bmod n\),固定一个起始点,求每个点到它的距离,排序就能得到在环上的相对顺序了。
注意是从 \(a_i\to b_j\) 连边,对于的距离要 \(-1\),同时还要判断一下是否有 \(a_i=b_j\) 的情况,如果有就令两点连双向 \(0\) 边使之完全等价。
CF521D Shop
- 给定 \(k\) 个正整数 \(a_i\) 和 \(n\) 个操作 \((t,i,b)\),操作分为 \(3\) 种:
- 若 \(t=1\),操作是 \(a_i\gets b\)。
- 若 \(t=2\),操作是 \(a_i\gets a_i+b\)。
- 若 \(t=3\),操作是 \(a_i\gets a_i\times b\)。
- 可以选择操作中至多 \(m\) 个,并按照一定顺序执行,求最大可能的 \(\prod a_i\)。
- \(n,k\leq 10^5,m\leq n\)。
降智罚坐,被 IV 痛骂。
\(1\) 操作转 \(2\) 操作是简单的,\(2\) 操作转 \(3\) 实际也不难,就是将 \(s\gets s+a\) 变为 \(s\times \dfrac{s+a}{s}\)。用一个堆贪心就行了。
CF521E Cycling City
- 给定一张无向简单图,问图中是否能找到两个点,使得两点之间有至少 \(3\) 条除端点外不交的简单路径。
- \(n,m\leq 2\times 10^5\)。
降智罚坐,被 IV 痛骂 \(\times 2\)。
一直往点双想,实际上后来看到题解区有个结论:当且仅当一个点双恰为一个环时无解,否则一定可以构造解。
但是讨论巨大多。
实际上,一个更简洁而本质的结论为:若存在两个相交的环时一定有解,否则一定无解。充要都显然。
那么直接跑个 dfs 生成树,对返祖边差分覆盖,找到一个被覆盖 \(\geq 2\) 次的树边就直接构造即可。
CF526F Pudding Monsters
- 给定 \(n\times n\) 的棋盘,共有 \(n\) 个棋子,且每行每列恰好一个。
- 求有多少 \(k\times k\) 的子矩形中恰好有 \(k\) 个棋子。
- \(n\leq 3\times 10^5\)。
这个是真的简单,不难发现 \(k\times k\) 中的极大情况就是有 \(k\) 个,很直觉的就变成 \(\max -\min=r-l\) 了。直接分治。
CF526G Spiders Evil Plan
- 给定一棵带边权的无根树,\(q\) 次询问,每次给定 \(x,y\)。
- 要求选择 \(y\) 条树上路径(可交)构成一个包含 \(x\) 的连通块,且最大化连通块的边权和。
- \(n,q\leq 10^5\),强制在线。
发现一个有 \(\leq 2y\) 个度数为 \(1\) 的点(叶子)的连通块(子树)能够被 \(\leq y\) 条路径覆盖。
然后选择 \(2y\) 个叶子到根的路径就是经典长剖 + 贪心,但是以每个点为根不能接受。
实际上,观察到最大的路径一定是该点到直径两端中的某个点,所以只用这两个点为根预处理。
注意直径端点一定是叶子,所以只有 \(2y-1\) 可以用,唯一问题是如果前 \(2y-1\) 条链不包含 \(x\) 怎么办。
再上贪心,无非两种情况:
- 去掉最后一条链换成 \(x\) 所在长链从底到上。
- 去掉 \(x\) 往上跳第一个到达的被选路径的一段,并改接为 \(x\) 所在的这段路经。
倍增预处理一下即可。
CF527E Data Center Drama
- 给定连通无向图,加尽量少的边,然后给边定向使得每个点的出入度都是偶数。
- 要求输出方案,可以有自环 / 重边。
- \(n\leq 10^5,m\leq 2\times 10^5\)。
比较刻意的构造,必要性探路。
每个点出入度都是偶数的必要条件是:作为无向图的时候,每个点的度数为偶数。
而这是无向图有欧拉回路的充要条件。
所以先将奇点配对连边,然后如果总边数为奇数再连一个自环,然后跑欧拉回路的同时,交替正负定向即可。
CF536D Tavas in Kansas
- 给定一张无向图,点有点权(可正负),边有边权。A 和 B 有各自的起点,两人博弈。
- A 先手,每次需要选择一个 \(d\geq 0\),将距离 A \(\leq d\) 的点都计入当前选手。
- 一个点不能被计入多次,如果全图的点均被计算了,那么游戏结束,得分高者获胜。
- \(n\leq 2\times 10^3,m\leq 10^5,|p_i|\leq 10^9\)。
简单 DP,模型转化。
对每个点计算出到 A,B 的最短路,分别离散化后,令 \(v_i\to (\text{dis}_{A}(i), \text{dis}_B(i))\),即表达在网格图上。
每次 A 的选择是覆盖前几行,而 B 的选择是覆盖前几列。
用 \(f(i,j,0/1)\) 表示覆盖了前 \(i\) 行,前 \(j\) 列,当前先手是 A/B 的 \(\min/\max\)。
如果强行枚举当前先手覆盖的长度,复杂度是 \(O(n^3)\) 的。
发现完全没有必要,因为转移过程本身就遍历了后续所有状态,不间断,所以只考虑 \((i,j)\to (i+1,j)\) 和 \((i,j)\to (i,j+1)\) 即可。
CF538G Berserk Robot
- 给出 \(n\) 个限制,形如 \((t,x,y)\),表示第 \(t\) 个单位时间机器人在 \((x,y)\)。
- 构造长度为 \(l\) 的 NSEW 序列,表示机器人按照这个序列循环不断移动,满足上述限制,或者判断无解。
- \(n\leq 2\times 10^5,l\leq 2\times 10^6,t_i,|x_i|,|y_i|\leq 10^{18}\)。
虐心题,代码调一上午。
大概思路是求出每 \(l\) 次移动的 \(\Delta x\) 和 \(\Delta y\),之后将每个限制变为 \(((t-1\bmod l)+1,x-\Delta x\times \lfloor\dfrac{t-1}{l}\rfloor, y-\Delta y\times \lfloor\dfrac{t-1}{l}\rfloor)\)。
转化到一个循环里,对于新的 \((t',x',y')\),首先时间相同的限制要一样,其次满足两点:
- \(x'+y'\equiv t'\pmod 2\)。
- \(\forall i,j,t'_i>t'_j\),满足 \(t'_i-t'_j\geq |x'_i-x'_j|+|y'_i-y'_j|\)。
这样每次就全力往某个方向走,多余的一定是偶数个,直接反复横跳即可。
关键是,如果不存在初始 \((t-1)\bmod l\) 相等的对,找到 \(\Delta x\) 和 \(\Delta y\) 并不简单。
于是转变思路,用上面的必要条件反向找可行的 \(\Delta x\) 和 \(\Delta y\)。
对于奇偶性的限制,直接暴力枚举奇偶性,看是否可行即可。
对于不等式,将所有 \(t,x,y\) 都用上述方法转变为带未知元 \(\Delta x,\Delta y\) 的方程,把 \(|a|+|b|\) 等价拆为 \(\max(a+b,a-b,-a+b,-a-b)\)。
然后就得到了一系列 \(\Delta x+\Delta y\) 和 \(\Delta x-\Delta y\) 的限制,枚举 \(\Delta x\in[-l,l]\),根据另一限制和奇偶性找 \(\Delta y\) 即可。
CF538H Summer Dichotomy
- 给定 \(n\) 个区间,求将区间分为两部分,某一部分可以为空。
- 使得两部分区间分别有交,且交相加后与 \([t,T]\) 有交。同时有 \(m\) 条两个区间不能在同一部份的限制。
- \(t\leq T\leq 10^9,n,m\leq 10^5\)。
妙妙题。
首先这题看着很 2-sat。先将 \(m\) 条边连接,跑二分图判定,得到黑白两个区间。
这样就相当于对每个连通块,它的两个区间必须分选,特别的,单点只有自己的区间 和 一个空区间,符合 2-sat 模型。
考虑限制,首先每部分区间有交,先把 \(\max l\) 和 \(\min r\) 拿出来。
-
如果 \(\max l \leq \min r\),说明任意区间集合均有交,且都包含 \([\max l,\min r]\)。
只需要找一个 \(v\),满足 \(v\) 属于某个区间,且 \([\max l+v,\min r +v]\) 和 \([t,T]\) 有交即可,并不难。
-
如果 \(\max l>\min r\),两者必须分属两个部分。
但是这个思路后续似乎就不明朗了,看过题解后才发现应该直接贪心。
因为 \(\max l\) 和 \(\min r\) 是最松松松的限制了,\(\max l\) 不能变小,\(\min r\) 不能变大。
所以如果 \(\max l+\min r<t\) 就加 \(\max l\),\(>T\) 就减 \(\min r\),然后就令两个点为最终决策点。
对必须选一个的跑二分图染色,不冲突即可。
CF547D Mike and Fish
- 给定平面内 \(n\) 个点,构造黑白染色使得对任意行或任意列,两颜色差的绝对值 \(\leq 1\)。
- \(n,x_i,y_i\leq 2\times 10^5\)。
经典题。
将点表达到边上,行列连边,得到二分图,将奇点统一连向一个虚点,这样图就有欧拉回路了。
对欧拉回路中,从左往右的染白,从右往左的染黑即可。
CF547E Mike and Friends
- 给定 \(n\) 个字符串。
- 多次询问 \((l,r,k)\),求 \(s_k\) 在 \(s_l \sim s_r\)中出现了多少次。
- \(n,\sum |s|\leq 2\times 10^5,q\leq 5\times 10^5\)。
论你写完题解后发现一道题的题解通道已关闭(
好像是没有人提出的做法。
因为 \(\text{len} = \sum |s|\leq 2\times 10^5\),所以不同的 \(|s|\) 个数只有 \(O(\sqrt{\text{len}})\) 种,这是经典根号分治。
也就是说,每个串中只有 \(O(|s|\sqrt{\text{len}})\) 个子串有贡献,这是可以接受的。
但是不能把这些子串都塞入 Hashtable 中,MLE 了。
但是也不难,直接将初始的 \(n\) 个字符串塞入 Hashtable 中,每次把子串的贡献加到 \(\text{cnt}_i\) 上(该子串与 \(s_i\) 相等)。
然后离线差分一下就没了,时间复杂度 \(O(n\sqrt n)\)。
小彩蛋:一开始写 unsigned long long
自然溢出的 Hash 被 hack 了,CF 果然名不虚传。
当然一开始就把所有串扔到 AC 自动机里去,离线标记 + 树状数组维护子树和也很经典了。
好像 SA + 二维数点也很经典了(这就是一套路满满题
CF553E Kyoya and Train
- 给定有向图,边有代价 \(c\) 和 \(t\) 个概率,分别表示经过这条边花费 \([1,t]\) 个单位时间的概率。
- 如果在 \(t\) 时刻之后到达 \(n\),需要交 \(x\) 元罚款。求最优决策下,从 \(1\to n\) 的期望最小代价。
- \(n\leq 50,m\leq 100,t\leq 2\times 10^4,x,c_i\leq 10^6\)。
科技题。
一开始想了很久正着 DP,突然发现目标明确直接逆着 DP 就好了。
设 \(f(u,i)\) 表示 \(i\) 时刻到达 \(u\),从 \(u\to n\) 还要花费的最小期望代价。
- \(f(n,*)=[i>t]x\)。
- \(f(*,t+1)=\text{dis(*,n)}\)。(最短路)
- \(\displaystyle f(u,i)=\min_{(u,v,w)\in E} \left( \sum_{i=1}^{t} p_{u,i}\times f(v,i+t)\right)\)。
然后直接差卷积 FFT,发现转移没有单调性,所以用 SPFA。看题解区据说复杂度并非 \(O(nmt\log t)\) 的,但是能过也不知道咋卡。
正解是分治 FFT,也不知道是啥科技(
CF555E Case of Computer Network
- 给定无向图,判断是否能将边定向使得给出的 \(q\) 对 \((s,t)\) 都存在 \(s\to t\) 的路径。
- \(n,m,q\leq 2\times 10^5\)。
结论题。
老早就被灌输过一个 边双一定能定向为强连通分量 的结论,没想到还真能拿来出题。
直接边双缩点 + 给树上路径定向即可。实现时我还用了树上并查集,实际直接差分即可。
这个结论的证明:
考虑找到边双中任意一个环,并统一定向。
然后找到边 \((u,v)\) 使得 \(u\) 在环中但 \(v\) 不在,如果找不到说明整个边双已经是强连通分量了。
然后就找到 \(v\) 到环,但是不经过 \((v,u)\) 这条边的路径,并将这条链统一定向,融入视为“环”的一部分。
一定能成功,因为边双 \(v\to u\) 至少有两条路径,也自然有 \(v\) 到环的路径。
CF559E Gerald and Path
- 给定 \(n\) 条线段,给出它的一个端点和长度,求所有线段覆盖的最大长度。
- \(n\leq 100\)。
厉害题。
一开始的想法是:先将线段按给定端点排序,设 \(f(i,j,0/1)\) 表示从前往后考虑到了 \(i\),当前最右端是 \(j\),\(j\) 的状态是往左/右。
然后转移的时候只考虑最右端点往右的贡献,因为(我认为),如果往左右贡献只能是完全包含先前线段,那还不如先前线段不被加入。
实际有严重问题,那就是先前线段可能有往右的贡献!!!
解决方法,同样的状态,类似的转移,但是当 \(f(i,j,k)\to f(o,p,q)\) 的时候,还考虑 \([i+1,o]\) 中最右端点 \(p\) 的贡献。
实际上很顺理成章的嘛,因为本身状态就这么设计的,连最右端的贡献都不计入怎么行(
只能说是核心思路想到了但实现出大问题。
CF566C Logistical Questions
- 给定一棵树,有点权边权。
- \(u\to v\) 的距离定义为 \(a(v)\times \text{dis}^{\frac{3}{2}}(u,v)\),求树的带权重心。
- \(n\leq 2\times 10^5\)。
不会求导ing
对于一类带权重心的经典解法就是调整法,每个时刻至多存在一条边,使得往该子树移动的带权重心减小。
原因是距离函数是下凸的,多个下凸函数的叠加还是下凸的。
问题是如何快速判断往哪个子树移动,之后可以用经典点分治多个 \(\log\) 解决。
看式子,沿着边 \((u,v,w)\) 移动的结果是:
如果往一个方向的函数值会减小,那么对它求导看哪个 \(<0\) 即可,即观察:
的正负性。
CF566E Restoring Map
- 给定树上 \(n\) 个点的点集,各自的点集均由距离自己 \(\leq 2\) 的所有点构成。
- 并不知道每个集合对应哪个点,要求构造原树。
- \(n\leq 10^3\)。
这种题目就是要 dfs 式的找性质。
发现距离为 \(3\) 的节点的交集大小恰好 \(=2\),且这两个点一定直接连边。
因此除了 \(n=2\)(直接特判)的情况,所有非叶子节点直接的连边都能确定。
如果出现非叶子节点个数 \(=2\) 的情况,不能通过集合区分叶子,但只会有两类叶子集合,分别挂在不同节点上即可。
否则对于叶子节点,能够确定它对应的集合,就是所有包含它的集合中,大小最小的一个。
要找到叶子的父亲,就是看只保留非叶子节点时,哪个集合与之相等。全程判断需要用 bitset
优化。
学会了遍历 bitset 的正确姿势:
for(int k = now._Find_first(); k != now.size(); k = now._Find_next(k))
CF568C New Language
- 将 \(\texttt{a}\) 开始的 \(l\) 个字符分为两个集合。
- 利用这 \(l\) 个字符构造满足 \(m\) 个限制的长度为 \(n\) 的字符串。还要求构造串的字典序不小于给定串 \(s(|s|=n)\)。
- 每个限制形如:若 \(p_1\) 上的字符 \(\in\) 集合 \(t_1\),那么 \(p_2\) 上的字符 \(\in\) 集合 \(t_2\)。
- \(l\leq 26, n\leq 200,m\leq 4n(n-1)\)。
一眼 2-sat + 按位贪心。
CF568E Longest Increasing Subsequence
- 给定长度为 \(n\) 的序列,有 \(k\) 个空缺。给定 \(m\) 个数用于填补空缺。
- 输出严格上升子序列最大的方案。
- \(n\leq 10^5,k\leq m\leq 10^5,k\leq 10^3\)。
考虑求严格上升子序列的 \(O(n\log n)\) 做法,维护的是当前长度为 \(i\) 的上升子序列的最小末尾。
在这里发现可以在每个空缺直接把 \(m\) 个数都插进去,因为严格上升代表转移不重。每次双指针就是 \(O(n+mk)\) 的。
个人认为最大难度在方案输出。
逆向构造是一定的,需要记录 \(f(i)\) 表示 \(i\) 位置的上升子序列,非空缺能够直接记录个 \(\text{pre}\)。
空缺先看能否转移到非空缺,如果不能就贪心的用最大的一个数填补。
CF571D Campus
- 维护两类集合和一个序列,初始每类 \(n\) 个集合,\(i\) 号集合下有且仅有 \(i\)。支持 \(5\) 种操作:
U x y
:将第一类中 \(x,y\) 所在集合合并。M x y
:将第二类中 \(x,y\) 所在集合合并。A x
:将第一类中 \(x\) 所在集合的下标在序列中均对应加上该集合大小。Z x
:将第二类中 \(x\) 所在集合的下标在序列中均赋值为 \(0\)。Q x
:单点查询。
- \(n,m\leq 5\times 10^5\)。
维护一个点加入集合的时间,就有一个显然的 \(O(n\log ^2 n)\) 的并查集做法了。
CF573E Bear and Bowling
- 给定长度为 \(n\) 的序列 \(a\),求最大权值子序列 \(b\)。
- 子序列的权值定义为 \(\sum_{i=1}^{|b|} ib_i\)。
- \(n\leq 10^5,|a_i|\leq 10^7\)。
\(O(n^2)\) 的 DP 式是很好得到的,之后就比较难动手,考虑了一会转移到网格图上。
然后突然发现转移的单调性,就是一定有一个位置,使得 \(f(i,j)\) 之前的 \(j\) 是继承,之后的 \(j\) 是转移。
这样相当于需要在线维护 后缀加等差数列 和 单点查询。
这里我傻了,想了半天会了一个 平衡树 + 矩阵 的维护方法, 虽然更有普适性但是 1min 的时间真的不如写卡常的暴力(
实际上差分就变成后缀加了,每次查询前缀和即可 QwQ
CF575A Fibonotci
- 对于序列 \(f\),\(f_0=0,f_1=1\),\(f_i=s_{i-1}f_{i-1}+s_{i-2}f_{i-2}\)。
- \(s_0\sim s_{n-1}\) 给定,之后有 \(m\) 个位置的 \(s_i\) 也给定,其余 \(s_i=s_{i\bmod n}\)。
- 求 \(f_k\bmod p\)。
- \(n,m\leq 5\times 10^4,k\leq 10^{18},s_i,p\leq 10^9\)。
一开始傻了不知道怎么用一个矩阵表示 \(n\) 个转移。实际上用 \(n\) 个矩阵即可……
对 \(n\) 个矩阵倍增预处理,对给定位置特殊处理即可。
实现上的一个细节是连续的给定位置会对矩阵有连续的影响,要同时考虑。
CF575E Spectator Riots
- 给定多个图形,每个图形中随机撒一个点。
- 在所有给定图形中找 \(3\) 个点,使得它们的外接圆期望覆盖的点尽量多。
- 如果有多个方案输出外接圆半径最大的,还有就任意输出。
- \(n\leq 10^5\)。
题面是骗人的,实际一定存在覆盖所有图形的方案。
考虑一个无限大的圆不断缩小,直至接触到凸包上至少 \(3\) 个点。如果 \(3\) 个点不相邻那肯定移动到相邻覆盖范围更严格大。
所以感性理解以下在凸包上找 \(3\) 的相邻点的最大外接圆半径即可~
CF575I Robots protection
- 维护二维平面 \((0,0)\sim (n,n)\),支持两种操作:
- 加入一个两条直角边平行于坐标轴的等腰直角三角形。
- 询问一个点被多少个三角形覆盖。
- \(n\leq 5\times 10^3,m\leq 10^5\)。
直接做是 \(4\) 维偏序,不能通过。值域这么小显然是用来给二维树状数组的,所以目标是优化到 \(3\) 维偏序。
由于图形是对称的所以只考虑一种,发现可以简单容斥,如图:
可以先把 \(AB\) 以右的一个矩形 \(+1\)(\(x_0\in [x,n],y_0\in[y,y+\text{len}]\))。
再把多余部分 \(-1\)(\(x_0+y_0>x+y+\text{len},y_0\in[y,y+\text{len}]\))。
其余几种也都是这种形式。
CF576D Flights for Regular Customers
- 给定一张 \(n\) 个点 \(m\) 条边的有向图。一开始在 \(1\) 号节点,要走到 \(n\) 号节点。
- 只有当你已经走过了至少 \(d_i\) 条边时,你才能走第 \(i\) 条边。
- 问最少要走多少条边,或判断无法到达。
- \(n,m \le 150\),\(d_i \le 10^9\)。
经典矩阵乘法,每次单边激活即可。
CF576E Painting Edges
- 给定一张 \(n\) 个点 \(m\) 条边的无向图。
- 一共有 \(k\) 种颜色,一开始,每条边都没有颜色。
- 定义合法状态为仅保留染成 \(k\) 种颜色中的任何一种颜色的边,图都是一张二分图。
- 有 \(q\) 次操作,第 \(i\) 次操作将第 \(e_i\) 条边的颜色染成 \(c_i\)。
- 但并不是每次操作都会被执行,只有当执行后仍然合法,才会执行本次操作。
- 你需要判断每次操作是否会被执行。
- \(n,m,q \le 5 \times 10^5\),\(k \le 50\)。
有些新意但是还是很板的线段树分治,可以看作是假的强制在线,按时间顺序走即可。
CF578E Walking!
- 给定长度为 \(n\) 的只包含
L
或R
的字符串 \(s\)。 - 构造 \(n\) 的排列 \(p\) 满足 \(s_{p_i}\neq s_{p_{i+1}},i\in[1,n)\),同时最小化 \(\sum_{i=1}^{n-1}[p_i>p_{i+1}]\)。
- \(n\leq 10^5\),保证数据有解。
中规中矩的构造题。
得到答案相对简单,维护所有候选集合,如果当前字符能够加到某个集合末尾就直接加,否则只能新开一个。
答案就是集合数 \(-1\),比较关键的是构造。
集合内部和构造无关,根据集合首尾定义 \(4\) 种集合:LL
、LR
、RL
、RR
。
首先让 LR
和 RL
们合并成至多一个自己种类,同时 LL
和 RR
拼接消耗。
注意因为一定有解,所以 LL
和 RR
两种导致一种字符比另一种多一个的在互相拼接消耗后,一定一共只剩下一个。
如果它此时存在的话就只需要将 LR
和 RL
分别拼接在两端。
否则只有一种情况比较棘手,那就是只剩下一个 LR
和一个 RL
。
但此时根据讨论可以将一个串的开头放到另一个串的开头,从而形成 LL
和 RR
的局面,于是问题解决了。
CF582D Number of Binominal Coefficients
- 给定质数 \(p\) 和整数 \(\alpha ,A\),求满足 \(0\leq k\leq n\leq A\) 且 \(p^{\alpha}|\binom{n}{k}\) 的数对 \((n,k)\) 的个数。
- \(p,\alpha\leq 10^9,A<10^{1000}\)。
感觉像Kummer 定理这种的定理也就只能出现在数位 DP 中 QwQ
也就是说 \(\binom{n}{k}\) 中 \(p\) 的幂次等于 \(p\) 进制下 \(k+(n-k)\) 的进位次数,或者令 \(a=k,b=n-k\) 然后等价统计二元组 \((a,b)\) 的个数。
设 \(f_{i,j,0/1,0/1}\) 表示考虑到了从高到低第 \(i\) 位,进位了 \(j\) 次,第 \(i+1\) 位是否进位,\(a+b\) 是否顶到上界的方案数。
DP 的细节还是有的,有些系数甚至比较难推,举一例。
设 \(a',b'\) 分别表示 \(a,b\) 第 \(i\) 位的数字,满足 \(0\leq a',b'<p\),求 \(p\leq a'+b'<p+x_i\),即进位且受 \(A\) 的限制但之后 \(<A\) 的方案数。有:
其它系数大概也就这个级别的推导,不过有 \(6\) 个……
CF582E Boolean Function
- 给定表达式,只有 \(A,B,C,D,a,b,c,d\) 八个
bool
变量,且大小写字母相反。以及&
和|
两种操作符。 - 给定一个表达式,变量和操作符均可能是
?
表示通配。 - 给定 \(m\leq 16\) 组 \((A,B,C,D,x)\) 表示当 \(A,B,C,D\) 取值如此时,表达式的值为 \(x\)。
- 求合法的表达式个数。
- \(|s|\leq 500,n\leq 16\)。
建立表达式树,直接对 \(16\) 种状态状压,然后 fwt 维护转移即可,复杂度 \(O(|s|n2^{n})\)。
CF585E Present for Vitalik the Philatelist
- 给定长度为 \(n\) 的序列 \(a_i\),求二元组 \((x,S)\) 的个数。\(S\) 是一个包含 \([1,n]\) 中整数的非空集合,\(x\) 也是一个 \(\in[1,n]\) 的整数。
- 满足:\(x\not \in S\),\(\gcd _{i\in S} a_i>1\),\(\gcd(a_x,\gcd_{i\in S}a_i)=1\)。
- \(n\leq 5\times 10^5\)。
一开始看错题了还想了挺久(
比较套路的拿 \(\mu\) 作容斥系数即可,每个数至多贡献 \(2^8\) 个 \(\mu\) 有值的位置,所以复杂度挺优秀的。
CF585F Digits of Number Pi
- 给定字符串 \(s\),以及 \(d\) 位数 \(x,y\),求有多少 \(t\in[x,y]\) 且 \(t\) 有长度至少为 \(\lfloor\frac{d}{2}\rfloor\) 的子串是 \(s\) 的子串。
- \(|s|\leq 10^3,d\leq 50\)。
把 \(s\) 的所有长度为 \(\lfloor\frac{d}{2}\rfloor\) 的子串建立 ACM,直接数位 DP 即可。
CF587D Duff in Mafia
- 给定无向图,每条边有边权和颜色。
- 要求选出一组边,满足他们是一个匹配,且剩下的每种颜色的边也都构成匹配。
- 同时最小化选出的边权最大的边的边权,并输出。
- \(n,m\leq 5\times 10^4\)。
盯了挺久没有思路的,属实是傻了。
首先二分答案,然后每个顶点至少选一条边,每种颜色每个顶点处也至多选一条边,不是显然的 2-sat 的模型吗!!!
在每个顶点处前后缀和以下应该是挺好些的。
实际上每种颜色的边们可以直接暴力建,因为如果一个顶点处有 \(\geq 3\) 条同色边一定无解嘛。
CF587F Duff is Mad
- 给定 \(n\) 个字符串,多次询问 \(s_{l...r}\) 在 \(s_k\) 中出现了多少次。
- \(n,q,\sum_{i=1}^n |s_i|\leq 10^5\)。
一眼看成 CF547E QwQ
那题我就是拿根号分治过的,这里思考了以下发现之前的思路并不可行了,然后逐渐自闭。
实际上还是考虑根号分治,根据 \(|s_k|\) 分类,设 \(m=\sum |s_i|\)。
-
对于 \(|s_k|>\sqrt m\) 的:
因为这种串的个数很少,所以每次可以 \(O(m)\)。给 \(s_k\) 上的点标记,在 ACM 上预处理每个点的子树内的标记个数。
然后直接前缀和一下就能得到任意区间的答案了。
-
对于 \(|s_k|\leq \sqrt m\) 的:
可以 \(O(|s_k|)\) 就更简单了,考虑每个位置的贡献,只需要差分一下,每次 \(s_i\) 的子树 \(+1\) 即可。
根号平衡一下能做到 \(O(\sqrt m)\) 子树加和 \(O(1)\) 查询。
总时间复杂度 \(O(m\sqrt m)\)。
CF590E Birthday
- 给定 \(n\) 个字符串,保留尽量多的字符串,使得不存在一个字符串是另一个的子串。
- \(n\leq 750,\sum|s_i|\leq 10^7\),输出方案。
一眼根据 ACM 建立偏序集然后 Dilworth 最长反链,处理时只需要路径压缩。
需要注意的是当递归层数大到一定程度时,一定考虑递归栈的大小,例如这里 \(10^7\) 就一定不要写任何相关的 dfs。
然后人傻了不会 Dilworth 方案输出,编了好久网络流才猛然想起蓝书上都讲过……属实是基础不过关。
大体就是个调整法,一定有解什么的也挺好反证的。
传递闭包用 bitset 优化,如果匹配写个网络流的话,因为调整只需要 \(O(n^2)\),所以总时间复杂度是 \(O(\dfrac{n^3}{\omega }+n^2\sqrt n)\)(
CF603E Pastoral Oddities
- 给定一张 \(n\) 个点的无向图,初始没有边。
- 依次加入 \(m\) 条带权的边,每次加入后询问是否存在一个边集,满足每个点的度数均为奇数。
- 若存在,则还需要最小化边集中的最大边权。
- \(n \le 10^5\),\(m \le 3 \times 10^5\)。
充要条件是所有连通块都有偶数个点,考虑经典 dfs 树构造。
至于最小化最大边权,只需要用考虑 Kruscal 的方式,不断按边权从小到大加入边即可。
考虑到动态加边,利用 LCT 维护最小生成树的方式(边化点然后维护链的边权最大值)。
用一个堆维护当前生成树内的边集,再利用 LCT 维护子树和那一套维护每个连通块点数的奇偶性即可……
听起来和写起来都挺 shit 的,算是 LCT 大融合了,为的就是那一只 \(\log\) QwQ
否则有一个可以完全和 LCT 无关的 分治 + 并查集的 两 \(\log\) 做法。实测下来 LCT 的巨大常数完全打不过下面的好吧
CF605E Intergalaxy Trips
- 给定 \(n\) 个点的竞赛图,走过一条边需要一天,每条边每天出现的概率均为 \(p_{i,j}\)。
- 保证 \(p_{i,i}=1\),即可以在某个点等待。
- 求最优决策下 \(1\to n\) 的期望天数。
- \(n\leq 1000\)。
显然是设 \(E_i\) 表示 \(i\to n\) 的期望天数。
假设已知 \(E_i\) 的大小关系并将它们升序排序,那么每次的决策显然是从小到大选择第一个存在的边,同时如果 \(E_v>E_u\) 显然不如等待。
即:
移项得到最终结果:
问题是一开始只知道 \(E_n=0\),其余点不知道。
其实只需要利用类似 \(O(n^2)\) 的 Dijkstra 的思路,每次选择最小的 \(E\) 贡献给其余,动态维护每个未确定的 \(E_u\) 即可。
CF611H New Year and Forgotten Tree
- 给定每条边两端点 \(10\) 进制下的位数,构造对应的原树,或输出无解。
- \(n\leq 2\times 10^5\)。
有点好玩,感觉这个 idea 很神奇。
想了很多基于贪心的构造,但实际上需要一个核心观察:
将每种位数取一个关键点,如果合法,总存在一种构造使得这些关键点构成一棵子树,其余点均挂在关键点下。
关键点只有 \(m\leq 5\) 个,于是直接 \(O(m^{m-2})\) 枚举树的形态,然后就是一个二分图多重匹配。
CF613E Puzzle Lover
- 给定 \(2\times n\) 的字母矩阵,同时给定长度为 \(k\) 的字符串 \(s\)。
- 求有多少长度为 \(k\) 的有向路径,使得不经过重复格子,且按顺序构成了 \(s\)。
- \(n,k\leq 2000\)。
发现如果路径回头就没救了,所以一定是两端一个 U 形,然后中间蛇形路线(
因为路径有向直接钦定从左往右走然后 reverse 再做一遍,注意当 \(k\leq 2\) 时需要去重。
预处理 Hash 就能轻易得到左边的起始 U 形,中间则是简单的线性 DP,注意不重即可。
CF626G Raffles
- 有 \(n\) 种彩票,第 \(i\) 种有价值 \(p_i\),别人已经买了 \(l_i\) 张。
- 你可以买 \(m\) 张彩票。假设第 \(i\) 种买了 \(c_i\) 张,需要满足 \(c_i\leq l_i\)。
- 最大化 \(\sum \frac{c_i}{c_i+l_i} p_i\)。
- 每次修改会有 \(l_i\pm 1\),保证时刻有 \(l_i\geq 1\)。
- \(n\leq 2\times 10^5\)。
简单题。
静态的只需要一个堆维护 \(\max \Delta\) 即可,因为这是个减函数。
修改时也很容易发现只需要将当前决策中最小的 \(\Delta\) 不断拿出来比较即可,可以证明每次这样的修改都是 \(O(1)\) 的。