暑假集训题目合集-2
Day7
扫描线
一般使用线段树维护,具体地,维护区间和及区间非零个数。
[NOI2023] 方格染色
横竖线就是扫描线板题。斜线最多只有 \(5\) 个,暴力将能够合并的斜线合并,然后遍历所有横竖线判断是否有交。懒得写离散化了,直接动态开点线段树也能过。code
1 |
|
[SHOI2007] 园丁的烦恼
将一个询问拆成四个询问的差分形式,扫描线维护二维前缀和,动态开点线段树代替离散化。code
1 |
|
[IOI 1998][USACO5.5] 矩形周长 Picture
横线和竖线分开算。注意若出现多条线重合,则必须先处理加再处理删。code
1 |
|
Day8
树上技巧
树的直径的求法:
- 两遍 dfs/bfs(无法处理负边权) - 树形 DP(可以处理负边权)
这两种方法的时间复杂度均为 \(O(n)\)。
树形 DP 具体求法:
设 \(dp_{u,0/1}\) 表示以 \(u\)
为根的子树中从根向下能延伸的最长/非严格次长路径。则答案为 \(dp_{u,0}+dp_{u,1}\) 的最大值。
[APIO2010] 巡逻
老题了。考虑贪心,\(k=1\) 时连接直径两端是显然的。设直径为 \((u_1,v_1)\),加入的第二条边为 \((u_2,v_2)\),二者不交时答案显然为 \(dis(u_1,v_1)+dis(u_2,v_2)\),若两路径有交,形如
则答案为 \(dis(u_1,v_2)+dis(u_2,v_1)\)。由此可以看出,若仍要选在直径上的边,代价会更大。则我们将直径的边权全部设为
\(-1\),再找一个新的直径。
code
1 |
|
[NOI2021] 轻重边
结论:每次修改操作染不同颜色,重边数等于区间内相邻两点颜色相同的点对数。树剖+线段树维护即可。精细处理树剖的查询部分。code
1 |
|
[十二省联考 2019] 春节十二响
贪心策略:令两条链上各自权值最大的比较,次大的比较……则可以在每个节点开一个堆,启发式合并。不同于可并堆,节点 \(u\),\(v\) 的堆合并后的大小为 \(\max(size_u,size_v)\) 而非 \(size_u+size_v\),时间复杂度为 \(O(n\log n)\)。code
1 |
|
Day9
数论
「TAOI-2」喵了个喵 Ⅳ
神秘题。\(n\) 为偶数时显然。\(n\) 为奇数时先求出所有数的最大公约数 \(d\),此时取 \(x=2\),将所有数都约去 \(d\),此时若有奇数个奇数,则会有偶数个偶数,必然无解,反之则可以按照奇偶容易地构造一组解。最后答案为 \(2d\)。code
1 |
|
[CTSC2017] 吉夫特
这题的转化真是神了。发现题目中 \(\bmod 2\) 很特殊,\(\dbinom{a_{b_1}}{a_{b_2}} \times \dbinom{a_{b_2}}{a_{b_3}} \times \cdots \times \dbinom{a_{b_{k-1}}}{a_{b_k}} \bmod 2 >0\) 成立当且仅当对于任意 \(k>1\),\(\dbinom{a_{b_{k-1}}}{a_{b_k}}\bmod 2=1\),我们尝试使用 Lucas 定理展开\[\binom{a_{b_{k-1}}}{a_{b_k}}\equiv \binom{\lfloor a_{b_{k-1}}/2\rfloor}{\lfloor a_{b_k}/2\rfloor}\binom{a_{b_{k-1}}\bmod 2}{a_{b_k}\bmod 2}\pmod 2\] 持续展开,不难发现其等于两数二进制拆分后每一位的组合数相乘,又因为
\[\binom{1}{1}=\binom{1}{0}=\binom{0}{0}=1\] \[\binom{0}{1}=0\] 所以 \(\dbinom{a_{b_{k-1}}}{a_{b_k}}\bmod 2=1\) 当且仅当 \(a_{b_k}\) 在二进制下是 \(a_{b_{k-1}}\) 的子集,即 \(a_{b_{k-1}} \operatorname{bitand} a_{b_k}=a_{b_k}\)。则我们可以推出 DP 方程,设 \(dp_{i}\) 表示以 \(i\) 为结尾的子序列方案数:
\[dp_{a_i}=\sum_{a_i\in a_j\land j<i}(dp_{a_j}+1)\] \(O(3^{\log{\max(a_i)}})\) 子集枚举即可。
code
1 |
|
Day10
线性代数
[USACO07NOV] Cow Relays G
我们使用 \(\min\) 和 \(+\) 代替原矩阵乘法中的 \(+\) 和 \(\times\),也就是\[C_{i,j}=\min(A_{i,k}+B_{k,j})\] 设 \(A_{i,j}\) 表示 \(i\) 到 \(j\) 的最短路,则走 \(n\) 步后的最短路即为 \(A_{i,j}^n\)。
设离散化后点有 \(m\) 个,时间复杂度 \(O(m^3\log n)\)。
code
1 |
|
【模板】矩阵求逆
本题中的矩阵均为方阵。矩阵的逆:在模 \(p\) 意义下,若 \(B\times A=A\times B=I\),则 \(B\) 称为模 \(p\) 意义下 \(A\) 的逆矩阵,记作 \(A^{-1}\)。模 \(p\) 意义下,一个矩阵若有逆矩阵,则必然只有一个逆矩阵。
矩阵的逆可以用高斯-约旦消元求出。原理:使用初等行变换将矩阵 \(A\) 转化为单位矩阵 \(I\),同时对一个初始的单位矩阵 \(I\) 进行相同的初等行变换,最终得到的就是逆矩阵 \(A^{-1}\)。
例如,我们构造原矩阵 \([A\mid I]\),进行一系列初等行变换后,得到 \([I\mid A^{-1}]\)。我们发现,高斯-约旦消元的过程就是将矩阵的左半部分变为单位矩阵的过程,非常适合求解矩阵的逆。
无解判断:若消元过程中,主元与 \(p\) 不互质则无解。
code
1 |
|
Day11/12
离散与组合数学
[HAOI2008] 硬币购物
背包+容斥。首先求出没有任何限制下每种价值的方案数,设 \(dp_s\) 表示价值为 \(s\) 的方案数。子集枚举计算哪些硬币超出限制,若钦定第 \(i\) 中硬币超出限制,则该硬币至少总价值为 \(c_i\times (d_i+1)\),容斥计算即可。code
1 |
|
Devu and Flowers
在无限制时,通过隔板可以得到答案为 \(\dbinom{n+s-1}{n-1}\),若加上限制则考虑容斥。枚举子集,则状态 \(S\) 中所有子集元素均不合法的方案数为 \(\dbinom{s-\sum_{i\in S}f_i-|S|-1}{n-1}\)。这里不方便直接预处理阶乘算组合数,但是注意到 \(\dbinom{n}{m}\) 中,\(n\) 和 \(m\) 相差不会太大,所以可以直接通分后暴力计算。code
1 |
|
[CSP-S2019 江西] 多叉堆
并查集+组合。考虑合并过程。根一定是 \(0\),设合并前的大小为 \(size_x\) 和 \(size_y\),方案数为 \(cnt_x\) 和 \(cnt_y\),由于子树之间互不干扰,所以 \[cnt_{sum}=cnt_x\cdot cnt_y\cdot \binom{size_x+size_y-1}{size_x}\]code
1 |
|
[CEOI 2016] kangaroo
连续段 DP,一种很强的东西。\(dp_{i,j}\) 表示考虑放前 \(i\) 个数,构成 \(j\) 个合法连续段的方案数。在加入一个数时,可以有以下几种情况:- 并入某一个块,\(dp_{i-1,j}\times j\) 种情况。
- 自成一个新块,\(dp_{i-1,j-1}\times j\) 种情况。
- 将原来的两个块连接,合并成一个块,\(dp_{i-1,j+1}\times j\) 种情况。
特判 \(s\) 和 \(t\) 的限制。
code
1 |
|
[CSP-S2019] Emiya 家今天的饭
考虑使用总方案数减不合法方案数得到答案。总方案数为 \[\prod_{i=1}^n\left(1+ \sum_{j=1}^ma_{i,j}\right)-1\] 由于超过 \(\lfloor\dfrac{k}{2}\rfloor\) 的食材最多只可能有一个,所以考虑直接枚举是哪一个食材超限。\(dp_{i,j}\) 表示前 \(i\) 种烹饪方案选菜后,选择的菜品数与已选的总数之差为 \(j\),转移见代码code
1 |
|
Day13
摆摆摆。
Day14/15
单调队列优化 DP
没错又是我。
[HAOI2007] 修筑绿化带
我们可以将所有 \(C\times D\) 的矩形权值和缩为一个点记录在二维平面上(例如记录在 \(C\times D\) 矩形的右下角),那么题目就是对于每一个 \(A\times B\),在二维平面上取一个矩形内的最小值,这可以使用单调队列。具体地,按行扫一遍,记录答案,然后再按列扫一遍即可。code
1 |
|
[HAOI2007] 理想的正方形
code
1 |
|
斜率优化 DP
给定一个长为 \(n\) 的序列,每个位置
\(i\) 有 \(a_i,b_i\),\(a_i\) 单调递增。
对每个位置 \(i\) 求 \(\max_{j<i}(a_jc_i+b_j)\)。
当 \(c_i\) 单调时,显然可以使用单调队列
\(O(n)\) 解决。
对于每一个 \(a_i,b_i\),都对应一条直线
\(y=a_ix+b_i\),直接使用单调队列维护一个上凸壳。
[HNOI2008] 玩具装箱
设 \(dp_i\) 表示考虑前 \(i\) 个玩具时的最小总费用,设 \(sum_i\) 表示 \(C_i\) 的前缀和,容易得到状态转移方程 \[dp_i=\min_{j=0}^{i-1}(dp_j+((sum_i-sum_j)+(i-j-1)-L)^2)\] 设 \(s_i=sum_i+i,L'=L+1\),方程改写为 \[\begin{aligned} dp_i&=\min_{j=0}^{i-1}(dp_j+(s_i-s_j-L')^2)\\ &=s_i^2-2L's_i+\min_{j=0}^{i-1}(-2s_is_j+dp_j+s_j^2+2L's_j) \end{aligned}\] 容易发现,斜率 \(a_j=-2s_j\),截距 \(b_j=dp_j+s_j^2+2L's_j\),这样就可以使用单调队列优化了。时间复杂度 \(O(n)\)。code
1 |
|
数位 DP
[SCOI2009] windy 数(加强版)
\(dp_{i,j,0/1}\) 表示前 \(i\) 位数(高位),第 \(i\) 位为 \(j\),是/否被最大限制时的方案数。其中 \(j=10\) 表示高位前导 \(0\)。code
1 |
|
Day16/17
思维技巧
qmd 学长真的很强啊 orz。
讲了一种很强的思维方式:观察终态。
终态一般代指某个函数/解的形态。
一些题目中需要观察解长什么样子,寻找解可行的必要条件,并尝试证明它们是充要的。这种思路常用于无法通过简单方式描述解的场合。
另一些题目中需要调整,找到并剔除可能出现的不优的结构。这种思路常用于解集过于庞大,合法解缺少特殊性的场合。
还有一些题目中需要观察解的上下界。应用场合为最优化或构造问题。
LIS on Tree 2
首先排列是假的,我们直接考虑 dfs 序。LIS 难以以较低复杂度求出,我们重点关注 \(f(i)\)。一个重要的限制是 \[f(fa_i)\le f(i)\le f(fa_i)+1,\] \[f(1)=1,\] 这样,我们就可以将树划分为若干连通块,每个块内的点对答案贡献相同。构造连通块的方式就是将连通块内的 dfs 序反转,这样就只保留了连通块根部的贡献。这样问题就转化为选择一些子树,使得它们的 \(size\) 之和等于 \(K\)。那么,按照 \(size\) 从大到小贪心地选是正确的,证明考虑剥叶子。这主要运用了第一个思想。
另一种方法叫做规约。
首先我们需要解决一个问题,称为问题 1;
再加如一个问题 2;
若任何能解决问题 1 的算法都能解决问题 2,则说明问题 2 是不强于问题 1 的;
以上就是规约的步骤。容易发现,它实质上是对问题的转化。
Delete AAB or BAA
规约:考虑将原问题转化为:给一个只含 A 和 B
的串,按照 AAB 或 BAA
的形式删除,问能否删成空串。尝试观察终态,发现:
一个子串能被删空的必要条件是
A的数量是B数量的 \(2\) 倍;若一个串被切成两个子串,且这两个子串能被删空,则它也必然能被删空;
根据观察 2,我们考虑不能被断开但是能被删空的串 ABAAAB
如何描述。
结论:
- 符合观察 1,且串首位不同的串是可被删空的串。
接下来研究原问题:
约定:\([l,r]\) 表示 \(S\) 从 \(S_l\) 到 \(S_r\) 之间含 \(S_l,S_r\) 的子串。
考虑 dp。设 \(f_i\) 表示 \([1,i]\) 中最多执行的操作数。转移: \[f_i=\max(f_{i-1},\max_{i\le j\le \lfloor
i/3\rfloor \land [i-3j+1,i] 能被删空}f_{i-3j}+j)\]