2023年 5月 做题记录

共9题.记于 6.1

关键词索引:斜率优化,退流,可行边,必须边,路径相关的二次扫描树上 dp,树上高斯消元.

P5017 [NOIP2018 普及组] 摆渡车

考虑在时间轴上 dp。
\(f[i]\) 表示在 \(i\) 处开始一次摆渡,\(i\) 时刻及以前的所有学生等待时间和的最小值。记最后一名学生开始等待的时间为 \(tmx\),则最终答案为 \(\displaystyle \min_{tmx \le i \le tmx+m}f[i]\)。因为当时刻大于等于 \(tmx\) 时,可以保证所有同学已经上车。
考虑 dp 转移式。枚举上一次上车的时刻 \(j\),则在 \((j, i]\) 内的学生需要等待此次摆渡车。记 \(sum[i]\) 表示 \(i\) 时刻及之前开始等待的学生开始等待的时刻之和,\(num[i]\) 表示 \(i\) 时刻及之前开始等待的学生的个数。有转移式:
\(\displaystyle f[i]=\min_{0 \le j \le min(0, i-m)} f[j]+i*(num[i]-num[j])-(sum[i]-sum[j])\)
发现可以斜率优化,即完成。

关于斜率优化:
对于形如 \(f[i]={max\;or\;min}(f[j]*g[i]+a[i]+b[j])\) 转移形式的 dp 方程。其特征是存在一个分别与\(i\)\(j\) 相关的函数相乘的项,考虑如下处理:对于一种可能的转移形如 \(f[i]=f[j]*g[i]+a[i]+b[j]\),写成 \(g[i]*f[j]+(a[i]-f[i])=-b[j]\)。发现如果将 \((f[j], -b[j])\) 视作平面上的一个点,则方程可被视作一个一次函数的截距式,其中 \(g[i]\) 为斜率,\(f[i]\) 的取值由截距决定。在意图最大或最小化 \(f[i]\) 的时候,往往会发现在枚举到的 \(j\) 中,仅有点集突壳对应的 \(j\) 可能会被选中。对其进行维护。

P3308 [SDOI2014]LIS

先介绍建模方法:
\(i\) 拆点为 \(in[i],out[i]\),建从 \(in[i]\)\(out[i]\) 边权为 \(b[i]\) 的边。求出以每个点结束的 LIS 长度记为数组 \(f[]\)。对于形如 \((i, j)\),满足 \(i<j,f[i]+1=f[j],a[i]<a[j]\) 的点对,建 \(out[i]\)\(in[j]\) 边权为 \(inf\) 的边。引入虚拟源汇点 \(S,T\)。对于 \(f[i]=1\) 的点,建 \(S\)\(in[i]\) 边权为 \(inf\) 的边;对于 \(f[i]=总序列LIS\) 的点,建 \(T\)\(out[i]\) 边权为 \(inf\) 的边。

这个图的最小割即为 \(S\)(最小代价)的答案。

再考虑证明它的正确性:
若存在一条没被割掉的路径,显然对应一种总序列 LIS 的选取方法,并且任意一种总序列 LIS 的选取方式都能在图上找到对应路径。

最后考虑最优字典序方案的构造:
将所有点按 \(c[]\) 排序,从小到大考虑每个点是否能被包含到最小割集中(本质上是贪心地构造一组最小割集)。对于一个点 \(i\),图上的边 \(e_i=(i \rightarrow i+n, w)\) 若可以存在于割集中,将 \(i\) 计入答案数组,从图上将 \(e_i\) 去掉。
补充1:最小割中的可行边和必须边退流

P3312 [SDOI2014]数表

\(\displaystyle \sigma_1(n)=\sum_{d|n}d\)

多组询问每次给出 \(n\), \(m\), \(a\),求\(\displaystyle \sum_{i=1}^{n}\sum_{j=1}^{m} [\sigma_1(gcd(i,j)) \le a]\sigma_1(gcd(i,j))\)

原式 \(\displaystyle =\sum_{d=1}^{n} [\sigma_1(d) \le a]\sigma_1(d) \sum_{i=1}^{n}\sum_{j=1}^{m} [gcd(i, j)=d]\)

\(\displaystyle =\sum_{d=1}^{n} [\sigma_1(d) \le a]\sigma_1(d) \sum_{i=1}^{\frac{n}{d}}\mu(i)\lfloor\frac{n}{di}\rfloor\lfloor\frac{m}{di}\rfloor\)

\(\sigma_{1}^{'}(n)=[\sigma_{1}(n) \le a]\sigma_{1}(n)\)\(T=di\)

上式 \(\displaystyle =\sum_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor \sum_{d|T}\sigma_{1}^{'}(d)\mu(\frac{T}{d})\)

预处理 \(\displaystyle g(T)=\sum_{d|T}\sigma_{1}^{'}(d)\mu(\frac{T}{d})\).单组询问可以 \(O(\sqrt n)\)回答.

对于 \(a\) 不同,\(g()\)会发生变化.我们考虑将询问离线按 \(a\) 从小到大排序.顺序扫描加点,发现加入一个新的 \(i\) 使得 \(\sigma_{1}^{'}(i)>0\)
时,会对满足 \(i|j\)\(g(j)\) 造成影响.即 \(g(j)+\sigma_{1}^{'}(i)*\mu(\frac{j}{u}) \rightarrow g(j)\)

我们使用支持单点修改区间查询和的数据结构维护 \(g()\),题目就做完了.

时间复杂度为 \(O(n\log^{2}n + n\sqrt{n}\log n)\)

P4126 [AHOI2009]最小割

其实是上接 P3308 [SDOI2014]LIS 中对最小割可行边和必须边的讨论.现在我会对其算法进行自己的解释和讨论.

注:感谢 command_block 题解和万能的 uoj 群友.

可行边指存在于至少一个最小割集中的边.
必须边指包含于任意最小割集中的边.
发现题目的两问分别为判断可行边和判断必须边.
我们现在考虑判断方法.

设最大流得到的某一个(任意一个)残量网络为 \(G\)

\(part\;1\) 可行边.

对于一条边 \(e\),如果它在 \(G\) 上不是满流(满流指最大流后边权减为 \(0\), 即被流满了),则将 \(e\) 的边权 \(-eps\)(即减少一个微小值)之后,最大流的大小没有变化;而如果其满流,这样操作最大流肯定会变小.若 \(e\) 不满流,则假设 \(e\) 存在于一种最小割集中,将 \(e\) 的边权 \(-eps\),最小割集的大小会发生变化,而根据最大流等于最小割,最大流也因发生变化,而这于上文的结论不符.这就证明了,存在一种最大流后的残量网络使得 \(e\) 不满流等价于(当且仅当)\(e\) 不被包含在任意一个最小割集中.
对于一条边 \(e=(u \rightarrow v, w)\) 在进行最大流后若被流满,则有可能为可行边,需要进一步确定判断.我们考虑若存在一种最大流后的残量网络使得 \(e\) 流不满,则应该满足可以找到 \(u \rightarrow v\) 的另一条增广路径使得 \(v\) 交还给 \(u\) 一些流量(流经 \(e\) 的)后,\(u\) 可以不通过 \(e\) 将其送到 \(v\).对应在当前的残量网络上,我们只需要判断 \(u\)\(v\) 是否在同一个强联通分量里即可(请注意,这里的强联通分量指的是由残量网络上不走边权为 \(0\) 的边后求得的强联通分量).

\(part\;2\) 必须边.

必须边集包含于可行边集.我们沿用 \(part\;1\) 中的思路,求出残量网络上不走 0 边后的缩点图 \(G^{'}\)\(G^{'}\) 的边集是原图中满流,并且在缩点后不成自环的边,即使用有残余流量边缩点得到的新图再用满流边连接).可以发现,\(G^{'}\) 上的边就是可行边集.任意一种最小割,应都是若干个 \(G^{'}\) 中的边组成的,并且 \(G^{'}\) 中任意一种紧的割都是最小割.
这里先提供一种构造最小割集的方法.将 \(G^{'}\) 上的点划分成两个联通块,一部分和 \(s\) 相连,记作 \(S\) 集,另一部分和 \(t\) 相连,记作 \(T\) 集,将 \(S\) 集和 \(T\) 集间的边割掉,即构造出了一种最小割.
我们对于 \(e=(u \rightarrow v)\),若 \(v\) 所在的强联通分量与 \(t\) 所在的强联通分量不同,我们构造 \(S=\left\{ x|x \in path_{s \rightarrow v} \right\}\),若 \(u\) 所在的强联通分量和 \(s\) 所在的强联通分量不同,我们构造 \(T=\left\{ x|x \in path_{u \rightarrow t} \right\}\).这两中情况都可以构造出 \(e\) 不割的一种最小割集出来,易知 \(e\) 不是必须边;而剩下的情况,即 \(s\)\(u\) 在同一强联通分量并且 \(v\)\(t\) 在同一强联通分量,可得知 \(e\) 一定为必须边.故也可以这样判断必须边:沿着残量网络中的非 \(0\) 边,\(s\) 可做到达 \(u\)\(v\)可以到达 \(t\)

P3365 改造二叉树

求保证中序排列递增所需要的最小修改节点个数.
考虑在中序排列的序列上 dp 最多可以保留不改的节点个数.设计 \(f_i\) 表示若 \(i\) 不改,前 \(i\) 个最多有多少可以不改.有转移 \(\displaystyle f_i=\max_{j<i,a_i-a_j \ge i-j} f_j+1\).我们分析条件 \(a_i-a_j \ge i-j\)\(a_i-i \ge a_j-j\).故整个序列中最多可以保留不改的节点个数即在新序列 \(b_i=a_i-i\) 中最长上升子序列的长度.

P5324 [BJOI2019]删数

需要重新解释“可删”并思考快速求出最小更改次数的方法.
我们考虑枚举元素 \(a_i\) 满足 \(a_i \in [1, n]\),把当前序列中等于 \(a_i\) 的元素在数轴的 \(a_i\) 位置垒到一起,向左推倒覆盖所及的区间.答案即为最后 \([1, n]\) 中没有被覆盖的整数的个数.
分析意义,对于任意一种“可删”序列,进行上述操作后会保证 \([1, n]\) 中每个整数都被覆盖一次.但由于序列长度为 \(n\),故只需保证每个整数都被覆盖即可.然后对于一个“非可删”序列,我们将覆盖中重复或大小在 \([1, n]\) 以外的元素变为在 \([1, n]\) 中空缺的整数,即构造出了一种最优秀的修改方案.
考虑操作,对于整体 \(+1\)\(-1\),我们直接左移或右移考察的区间 \([1, n]\),对于改变某一元素,在线段树容易维护两者覆盖区间的变化即可.

P6419 [COCI2014-2015#1] Kamp

非常经典的二次扫描树形 dp 题啊.
\(k\) 个人分布的点集为 \(K\).点 \(u\) 答案显然为 \(\displaystyle 2S_u-\max_{v \in K}{(\sum_{e \in path_{u-v}}w_e)}\).其中 \(S_u\) 表示 \(k\) 个点到 \(u\) 的路径覆盖的边的边权和.而式子后面的一部分是选出 \(u\)\(k\) 个点其中之一的最长路径.两部分都可以二次扫描解决.
值得总结的一点是,在关于最优化端点出发路径的二次扫描中,从 \(u\) 转移到 \(v\),即从 \(u\) 作为端点的路径到 \(v\) 作为端点的路径,存在两种情况.设一条以 \(u\) 为端点的路径是 \(path_{u-x}\).当 \(x\) 包含在 \(v\) 子树中时,\(path_{v-x}\) 要去掉 \(e(u, v)\).否则 \(path_{v-x}\) 中要加入 \(e(u, v)\).而通常的处理办法是在第一次和第二次扫描的 dp 数组中记下最优和次优路径,并都保证同一子树内只贡献一条(最优的)路径.记第一次扫描的 dp 数组为 \(f\),第二次为 \(g\).通过 \(g_u\)\(f_v\) 来推断 \(g_v\):子树内的路径 \(f_v\) 已经有了最优化结果,考虑直接加入 \(g_v\) 中,再判断出 \(f_u\) 中另一端点不在 \(v\) 子树内的最优路径用其更新 \(g_v\)

P3732 [HAOI2017]供给侧改革

\(a_i\) 为字符串中的第 \(i\) 个字符,\(S_i\) 为以 \(i\) 开头的后缀,\(LCP(S_i, S_j)\)\(S_i\)\(S_j\) 的最长公共前缀.

考虑 \(LCP(S_i, S_j)=k\) 的条件为 \(\forall i \le x \le i-k+1, a_x=a_{x-j+i}\).由于 \(a_i\) 是随机生成的,\(i,j\) 确定时,\(LCP(S_i, S_j)=k\) 概率为 \(\displaystyle \frac{1}{2^{k}}\).当 \(k\) 取到 \(40\),在整个串里存在两后缀的 \(LCP=k\) 的概率约为 \(\displaystyle \frac{n^2}{2^{40}}\),近乎为 \(0\).我们直接默认任意两串的 \(LCP \le 40\) 来做即可.这个概率的估算感觉颇有问题,但只考虑前 \(40\) 位是对的——笔者大概不能严谨证明,可以参阅其他题解...姑且这样吧.

将询问离线下来,挂在右端点上,从左往右扫描字符串.
设扫描到位置 \(r\).我们维护 \(g_i=data(i, r)\;(i<r)\),对于询问 \((l, r)\),答案为 \(\displaystyle \sum_{i=l}^{r-1} g_i\)
现在考虑加入位置 \(r\) 后,\(g\) 会发生什么变化.枚举 \(i<r\),发现 \(LCP(S_i,S_r)\) 会被计入 \(g_x\;(x\le i)\) 中.但是枚举 \(i\) 时间复杂度显然不够优秀.我们利用 \(LCP \le 40\) 的结论,考虑枚举 \(LCP(i, r)\) 的值 \(len\).显然我们只需要找到 \(\displaystyle \max_{LCP(i, r)=len, i<r}i\)\(len\) 会被计入 \(g_x\;(x\le i)\).我们更新它们的最大值即可.

如何实现呢?
维护一棵 \(01\;Trie\),扫描到 \(r\) 时将 \(S_i\;(i<r)\) 的前 \(40\) 位插入到里面.对于 \(Trie\) 上的节点 \(u\),维护最后一次经过过它的后缀编号为 \(mx_u\).在 \(Trie\) 上跑 \(S_r\),对于经过的节点 \(u\),设其深度是 \(len_u\),发现 \(\displaystyle mx_u=\max_{LCP(i, r)\ge len_u, i<r}i\).然后前缀更新 \(g_i\) 的最大值即可.又发现 \(g_i\) 只有前缀更新最大值的操作,故\(g_i\) 单调不降,我们用线段树维护 \(g_i\),可以在更新 \(g_i\) 时二分出第一个需要更新的位置,再做一个区间覆盖即可.

现在到了复杂度分析环节.时间复杂度 \(O(40n\log n)\),空间复杂度 \(O(40n)\).可以(勉强)通过此题.

这个做法借鉴了线段树维护历史版本和(扫描线)的思想.现在做区间的子区间脑子里全是扫描线.

Random Walk

\(F_u\) 为经过 \(u\) 的期望次数,\(d_u\)\(u\) 的度数.有转移

\[F_u= \begin{cases} \frac{F_{fa}}{d_{fa}}+[u=S]+\sum_{v}\frac{F_v}{d_v} &(u\neq T)\\ 1 &(u=T) \end{cases} \]

发现这是一个高斯消元的形式.现在介绍通过树上 dp 完成 \(O(n)\) 树上高斯消元的方法.
请注意,下面是对于树上高斯消元的介绍,与前面的转移方程无关

设需要求解 \(F_u(u \in {1,2,...n})\).有转移方程

\[F_u=k_{fa}F_{fa}+\sum_{v}k_vF_v+d \]

我们考虑将 \(F_u\) 表示成只和 \(F_{fa}\) 和一常数有关的式子:\(\displaystyle F_u=g_uF_{fa}+c_u\)

现在考虑如何求解 \(g, c\)

\[\begin{aligned} F_u &=k_{fa}F_{fa}+\sum_{v}k_vF_v+d \\ &=k_{fa}F_{fa}+\sum_{v}k_v(g_vF_u+c_v)+d \\ &=k_{fa}F_{fa}+(\sum_{v}k_vg_v)F_u+\sum_{v}k_vc_v+d \end{aligned} \]

\[\begin{aligned} (1-\sum_{v}k_vg_v)F_u&=k_{fa}F_{fa}+\sum_{v}k_vc_v+d\\ F_u&=\frac{k_{fa}F_{fa}}{1-\sum_{v}k_vg_v}+\frac{\sum_{v}k_vc_v+d}{1-\sum_{v}k_vg_v} \end{aligned} \]

易发现

\[\begin{aligned} g_u&=\frac{k_{fa}}{1-\sum_{v}k_vg_v}\\ c_u&=\frac{\sum_{v}k_vc_v+d}{1-\sum_{v}k_vg_v} \end{aligned} \]

先做一遍 dfs,将 \(g, c\) 数组求出.
在根节点处,\(g_{fa}=0\),可以直接求出 \(F_{rot}\) 的值.
再做一遍 dfs,将 \(F\) 数组求出即可.

posted @ 2023-07-13 22:36  ckain  阅读(39)  评论(0)    收藏  举报