Solution Set #10

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

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

160 UOJ 91 最大异或和

维护差分数组的线性基,那么问题就变成了 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 能被表出那么表出的子序列数量为 2n|B|,所以只需要计算 popcount=i 的数中有多少个能被表出。

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

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

163 P9999 [Ynoi2000] tmostnrq

有个 soft-O(n1.5) 的思路是:分块,然后建立每块的虚树。散块直接暴力,整块考虑几种情况:

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

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

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

代码鸽。

164 qoj7859. Bladestorm

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

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

分块维护树结构,复杂度 O(nn)

https://qoj.ac/submission/326513

165 2024.2.13 考试 T2

题目大意

区间 DP 的转移式子是:

  • f(i,j)max{f(i+1,j1),cost(i,j)}
  • f(i,j)max{f(i,k),f(k+1,j)}

二分之后可以利用 bitset 做到 O(n3lognw)。实际上不用二分,直接从小往大扫,并 DFS 更新 DP 值,注意到 DP 值只有 01,所以每个位置只会被更新一次,采用 bitset 优化这个过程,复杂度 O(n3w)

166 loj4040. 「SNOI2024」拉丁方

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

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

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

167 2024.2.13 考试 T3

题目大意

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

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

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

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

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

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

  • 区间加。
  • 查询区间 (ai2) 的和。

平凡的。

168 ARC118F Growth Rate

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

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

fi,j=kaijfi1,k

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

考虑另一个转移:

fi,j=kjaifi+1,k

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

做插值,看似复杂度是 O(n3),实际上 ai=1 的情况可以直接查表,所以复杂度为 O(n2logV)

Submission #50246111 - AtCoder Regular Contest 118

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

图上博弈题都好牛啊。

Hoof 有两种方法似掉:

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

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

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

  • 定义 colu=u
  • 如果 u 所有出边颜色均为 colv,则把 colu 赋值为 colv

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

启发式合并每个点的入边和出边,复杂度 O(nlog2n)

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

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

考虑求出单个问题的答案。从序列不降的情况入手,假设序列为 c1a1+c2a2+ckak(其中加号为序列的拼接,乘号类似定义),则有如下策略:不断把 a1 合并成 c12a1+1,如此重复直到序列中只剩下一个数。拓展到一般情况,则策略为:设 m=minai,把所有 ai=m 的连续段提出来。设连续段长度为 c1,c2,ck,那么把长度变为 c12,c22,,ck2,数值变为 m+1,再放回原位置。如此重复直到序列中只剩下一个数。

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

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

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

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

综上,问题可以在 O(nlog2n) 时间内被解决。

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

171 loj4042. 「SNOI2024」公交线路

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

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

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

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

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

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

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

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

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

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

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

173 loj3773. 「APIO2022」排列

考虑一个 2log2n 的做法:令 l=log2n,构造 l 个递增的数,并令 kk2l,然后在 k 的每个二进制位上插一个递减的序列。

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

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

174 loj3805. 「JOI Open 2022」长颈鹿

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

做到 O(n3) 是容易的,考虑 f[l,r],[x,y] 表示下标为 [l,r],值域为 [x,y] 的最大匹配数量。

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

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

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

https://loj.ac/s/2006046

175 loj3806. 「JOI Open 2022」放学路

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

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

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

https://loj.ac/s/2005926

176 qoj7439. 铃原露露

半个月前口胡的题(

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

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

https://qoj.ac/submission/330403

posted @   yllcm  阅读(116)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示