Solution Set #10

博主把趣题系列的大部分题做完了,准备开始随机做题了,写记录的时候会筛掉一些不太好的题。

你妈的,我怎么还是这么菜。

160 UOJ 91 最大异或和

维护差分数组的线性基,那么问题就变成了 \(\mathcal{O}(n+q)\) 次插入 / 删除。

把操作离线下来,那么元素可以看成三元组 \((l,r,x)\),表示出现时间是 \(l\),删除时间是 \(r\),值为 \(x\)。以 \(r\) 为关键字维护时间戳线性基即可。

https://uoj.ac/submission/676825

161 NOI 2017 整数

直接看这个

162 CF1336E1 Chiori and Doll Picking (easy version)

建立线性基转化问题。注意到 \(x\) 能被表出那么表出的子序列数量为 \(2^{n-|B|}\),所以只需要计算 \(\text{popcount}=i\) 的数中有多少个能被表出。

对线性基 mitm,第一部分搜索线性基 \([0,\frac{m}{2})\) 位,第二部分搜索线性基 \([\frac{m}{2},m)\) 位。注意到第二部分中数的 \([\frac{m}{2},m)\) 部分不受第一部分影响,所以直接记录 popcount,剩下的部分使用 FWT 合并即可。

https://codeforces.com/problemset/submission/1336/245312849

163 P9999 [Ynoi2000] tmostnrq

有个 soft-\(\mathcal{O}(n^{1.5})\) 的思路是:分块,然后建立每块的虚树。散块直接暴力,整块考虑几种情况:

  • 点在虚树外:往靠近虚树的方向移动。
  • 点在虚树一条虚链上:找下一个到达虚树上点的位置,这个可以对于每条链建立个前缀和数组表示两边点的数量差,二分以下就行。
  • 点在虚树的一个点上:直接预处理每个点经过每个后缀的操作之后到哪,预处理的方法可以考虑先操作一步然后归到上面的情况,递推。

这么做的动机是这类题的一种经典做法:快速处理平凡操作,暴力处理不平凡操作。

polylog 做法是直接考虑扫描线,每次把点在 \(l\) 时刻塞进 DS 里面然后在 \(r\) 时刻取出来。分析一下一次操作就是把 \(a_i\) 的祖先链上的点往下拉,其它点往上拉。如果合并相同的点,那么重剖之后有一个均摊:往下的点只会有 \(\log\) 次跨链操作,那么设势能为所有本质不同点到祖先的轻链数量和,那么势能总和是 \(\mathcal{O}(n\log n)\) 级别。所以快速处理链内移动即可。

代码鸽。

164 qoj7859. Bladestorm

容易得到一个贪心跳跃的方法:如果下一个位置距离当前位置小于 \(k\),那么直接跳 \(k\),否则跳到下一个位置。

如果把每个点向它的下一个点连边,那么可以得到一棵树,我们希望求出树上 \(0\) 点的深度。

分块维护树结构,复杂度 \(\mathcal{O}(n\sqrt{n})\)

https://qoj.ac/submission/326513

165 2024.2.13 考试 T2

题目大意

区间 DP 的转移式子是:

  • \(f(i,j)\gets \max\{f(i+1,j-1),\text{cost}(i,j)\}\)
  • \(f(i,j)\gets \max\{f(i,k),f(k+1,j)\}\)

二分之后可以利用 bitset 做到 \(\mathcal{O}(\frac{n^3\log n}{w})\)。实际上不用二分,直接从小往大扫,并 DFS 更新 DP 值,注意到 DP 值只有 \(0\)\(1\),所以每个位置只会被更新一次,采用 bitset 优化这个过程,复杂度 \(\mathcal{O}(\frac{n^3}{w})\)

166 loj4040. 「SNOI2024」拉丁方

拉丁方填数可以看作二分图完美匹配划分问题,或者说二分图最小边染色。有结论:二分图最小边染色是点度数的最大值。

求出一组最小边染色的方法如下:动态加边 \((u,v)\),设计函数 \(\text{dfs}(u,v,C_u,C_v)\) 表示染色 \(u,v\)\(u\) 的一组未染色颜色为 \(C_u\)\(v\) 的一组边染色颜色为 \(C_v\)。对于 \(C_u=C_v\),直接染色。否则,给 \(u\) 染上 \(C_u\),假设原本与 \(v\) 相连的颜色为 \(C_u\) 的点为 \(x\),调用 \(\text{dfs}(v,x,C_v,C_u)\)。容易证明递归不会成环。

提交记录 #2002988 - LibreOJ (loj.ac)

167 2024.2.13 考试 T3

题目大意

三元环计数考虑容斥,那么我们需要求:

  • 每个点的度数。
  • 三个矩形两两相交的矩形对数。

第一个问题是平凡的,考虑第二个问题。

扫描线,在矩形交的左端点位置统计答案。我们需要维护一个 DS,支持:

  • 加入 / 删除线段。
  • 求出某个区间内选出两个相交线段的方案数。

对于第二个问题使用 \(|V|-|E|\) 容斥来转化,即把线段交看成链。那么我们只需要维护数据结构:

  • 区间加。
  • 查询区间 \(\binom{a_i}{2}\) 的和。

平凡的。

168 ARC118F Growth Rate

对插值定义域问题的处理。

考虑插值。一般的 DP 转移式子为:

\[f_{i,j}=\sum_{ka_i\leq j}f_{i-1,k} \]

DP 第二维和值域有关,考虑插值优化。可以把转移看作先拉伸然后做一个前缀和的过程。然而由于我们没有定义实数域,所以拉伸后的结果未必是多项式。

考虑另一个转移:

\[f_{i,j}=\sum _{k\geq ja_i}f_{i+1,k} \]

此时拉伸变成了收缩,收缩之后的每一项对应到原多项式时都被定义过了,所以拉伸后仍然是多项式。

做插值,看似复杂度是 \(\mathcal{O}(n^3)\),实际上 \(a_i=1\) 的情况可以直接查表,所以复杂度为 \(\mathcal{O}(n^2\log V)\)

Submission #50246111 - AtCoder Regular Contest 118

169 loj3698. 「USACO 2022 US Open Platinum」Hoof and Brain

图上博弈题都好牛啊。

Hoof 有两种方法似掉:

  • 走到绝路了。
  • 两个棋子堵一起了。

先解决第一个。对反图拓扑排序,遍历过的节点就没救了,我们不妨把它们删掉。

考虑第二种情况,构造如下算法:

  • 定义 \(col_u=u\)
  • 如果 \(u\) 所有出边颜色均为 \(col_v\),则把 \(col_u\) 赋值为 \(col_v\)

容易发现,如果两个点颜色相同,那么它们一定能堵到一起。可以证明这是充要的,因为不满足条件的话 Hoof 有策略使得两点颜色始终不同。

启发式合并每个点的入边和出边,复杂度 \(\mathcal{O}(n\log^2 n)\)

提交记录 #2003364 - LibreOJ (loj.ac)

170 loj3697. 「USACO 2022 US Open Platinum」262144 Revisited

考虑求出单个问题的答案。从序列不降的情况入手,假设序列为 \({c_1}\cdot a_1+c_2\cdot a_2+\cdots c_k\cdot a_k\)(其中加号为序列的拼接,乘号类似定义),则有如下策略:不断把 \(a_1\) 合并成 \(\lceil\frac{c_1}{2}\rceil\)\(a_1+1\),如此重复直到序列中只剩下一个数。拓展到一般情况,则策略为:设 \(m=\min a_i\),把所有 \(a_i=m\) 的连续段提出来。设连续段长度为 \(c_1,c_2,\cdots c_k\),那么把长度变为 \(\lceil\frac{c_1}{2}\rceil,\lceil\frac{c_2}{2}\rceil,\cdots,\lceil\frac{c_k}{2}\rceil\),数值变为 \(m+1\),再放回原位置。如此重复直到序列中只剩下一个数。

尝试将这个做法拓展到原问题。我们直接对整个序列执行上面的算法,并尝试在这个序列上找到每个子区间的信息。尝试对于新序列上的每个元素上维护两个集合 \(Sl_i,Sr_i\),使得对于区间 \([l,r]\)\(l\in Sl_x,r\in Sr_y\),当前时刻 \([l,r]\) 对应的区间恰好是 \([x,y]\)。可以得到一个近似的构造:初始 \(Sl_i=Sr_i=\{i\}\),收缩连续段的时候,\(Sl_i\) 从右往左相邻两个合并,\(Sr_i\) 从左往右相邻两个合并(举例来说,收缩长度为 \(5\) 的连续段时,\(Sl\) 合并方式为 \(\{Sl_1,Sl_2\},\{Sl_3,Sl_4\},\{Sl_5\}\)\(Sr\) 合并方式为 \(\{Sl_1\},\{Sl_2,Sl_3\},\{Sl_4,Sl_5\}\))。这种构造在 \([l,r]\) 的连续段个数为 \(1\) 的时候是错误的,但对于其余情况正确。

值为 \(m\) 的连续段收缩之后会与值为 \(m+1\) 的连续段合并产生新的连续段。我们在合并连续段的时候,统计跨过两个连续段分界线的区间的答案。假设 \([l,r]\) 对应区间 \([x,y]\),则区间 \([l,r]\) 的答案为 \(m+\lceil\log_2(y-x+1)\rceil\)。枚举 \(\lceil\log_2(y-x+1)\rceil\) 即可在 \(\mathcal{O}((A+B)\log n)\) 的时间内计算答案(其中 \(A,B\) 为两个连续段长度)。

总结一下,上述算法分成两个部分:收缩连续段,合并连续段,我们分别说明两个部分的复杂度:

  • 对于收缩连续段,一次收缩会在 \(\mathcal{O}(|S|)\) 的时间内删除 \(\frac{|S|}{2}\) 个元素,由于每个元素只会被删除一次,所以复杂度为 \(\mathcal{O}(n)\)(注意当 \(|S|=1\) 的时候,我们忽略收缩操作)。
  • 对于合并连续段,注意到合并之后的集合都会进行至少一次收缩操作,所以需要合并的集合大小之和同样是 \(\mathcal{O}(n)\)。使用上述复杂度为 \(\mathcal{O}((A+B)\log n)\) 的方法,分治合并多个集合,可以得到总复杂度为 \(\mathcal{O}(n\log^2 n)\)

综上,问题可以在 \(\mathcal{O}(n\log^2 n)\) 时间内被解决。

提交记录 #2003538 - LibreOJ (loj.ac)

171 loj4042. 「SNOI2024」公交线路

条件等价于存在一个点 \(u\) 使得所有叶子和 \(u\) 的最短路径都是 \(1\)

点减边容斥,枚举点 \(u\),容斥计算以 \(u\) 为根的方案数。具体地,我们只考虑和叶子相连的跨过 \(u\) 的边,对于 \(u\) 的每棵子树,枚举钦定多少个点一条边都不选,并确定它与非叶子结点及前面已经遍历过的叶子的连边情况,容易 DP 计算。此时复杂度为 \(\mathcal{O}(n^3)\)

考虑优化。随便钦定一个根,那么我们只容斥 \(u\) 子树的部分,子树外的部分可以快速算出合法的方案数,复杂度和树形背包的复杂度一致,为 \(\mathcal{O}(n^2)\)

提交记录 #2003737 - LibreOJ (loj.ac)

172 loj2330. 「清华集训 2017」榕树之心

从判断根的可行性开始考虑。先判掉奇偶性的问题,有几点观察:

  • 如果根是重心那么一定能完成构造。
  • 如果根不是重心,那么一定朝重心方向走若干步,走回来之后在将剩下的点匹配。

我们希望走的点越多越好。设计 \(f_u\) 表示 \(u\) 为根走若干步,剩下的结点最少是多少个。那么考虑重儿子,如果重儿子能够剩下的点不超过其余点的数量,则能够完成匹配,\(f_u=[2|sz_u]\);否则,\(f_u=f_v+1-(sz_u-sz_v-1)\),其中 \(v\) 是重儿子。

回到判断任意点的问题,实际上只需要把到根的路径缩成一个点,归到上面的问题。可以证明一定存在对应的构造方式。

所以实际上是 DP 题啊,我以为有什么充要条件来着……

提交记录 #2004600 - LibreOJ (loj.ac)

173 loj3773. 「APIO2022」排列

考虑一个 \(2\lfloor\log_2 n\rfloor\) 的做法:令 \(l=\lfloor\log_2 n\rfloor\),构造 \(l\) 个递增的数,并令 \(k\gets k-2^l\),然后在 \(k\) 的每个二进制位上插一个递减的序列。

注意到 \(lim=1.5\lfloor\log_2 n\rfloor\),我们保留 \(l\) 个递增的数,并用 \(0.5\lfloor\log_2 n\rfloor\) 次操作构造出所有二进制位。假设有两个连续的 \(1\),那么我们可以找到前面插入的最小值和次小值,然后插一个恰好比它们大的数,这样经过这个数的所有子序列的起点恰好有 \(3\) 个,即对答案的贡献是 \(3\cdot 2^x\),可以通过。

提交记录 #2005266 - LibreOJ (loj.ac)

174 loj3805. 「JOI Open 2022」长颈鹿

发现合法序列的构造方式是:每次把最小值或者最大值放在开头或结尾。

做到 \(\mathcal{O}(n^3)\) 是容易的,考虑 \(f_{[l,r],[x,y]}\) 表示下标为 \([l,r]\),值域为 \([x,y]\) 的最大匹配数量。

考虑这个转移在干什么,实际上就是不断缩小一个矩形,使得每个矩形的一个边角上都有一个点 \((i,p_i)\)。那么每次转移相当于 \(\mathcal{O}(n^2)\) 个修改和 \(\mathcal{O}(n)\) 个矩形查询,只能用树套树做到 \(\mathcal{O}(n^2\log^2 n)\)

注意到转移的权值都是 \(+1\),考虑换维。设 \(f_{i,j,4}\) 表示 \((j,p_j)\) 为边界的四个方向的矩形在答案为 \(i\) 时最小的边长,这样修改降到了 \(\mathcal{O}(n)\),可以少一个 \(\log\)

因为数据随机,所以 \(i\) 大约是 \(\mathcal{O}(\sqrt{n})\) 级别,与随机排列下 LIS 的期望长度相当。所以复杂度是 \(\mathcal{O}(n\sqrt{n}\log n)\)。有 \(16\) 倍常数,跑的飞慢。

https://loj.ac/s/2006046

175 loj3806. 「JOI Open 2022」放学路

问题在广义串并联图上是容易的。

考虑非广义串并联图怎么做,发现 \(K_4\) 无解。所以可以直接按照上面的方法做。但是不一定有 \(K_4\) 同胚子图就无解,因为有些点不会被任何 \(1\to n\) 的路径经过。把这些点删掉就可以了。

偷懒没有删点,还是能过。

https://loj.ac/s/2005926

176 qoj7439. 铃原露露

半个月前口胡的题(

考虑构造一个判断条件,一个简单的构造是 \(u\) 不被包含且 \(u\) 的儿子中有两个儿子有点,那么就不合法。那么一个暴力就是把子树中的点全部提出来,对于 \(l>a_u\) 的所有左端点,找到只包含一种颜色的最右的右端点,对于 \(r<a_u\) 的所有右端点同理。这样每个左端点只有一段右端点合法,每个右端点只有一段左端点合法,即可转化为二维数点问题。

考虑 set 启发式合并求出范围。每次插入的时候找到前驱和后继,用线段树做 chkmin/chkmax 即可。复杂度 \(\mathcal{O}(n\log^2 n)\)

https://qoj.ac/submission/330403

posted @ 2024-02-17 19:33  yllcm  阅读(84)  评论(1编辑  收藏  举报