Cry_For_theMoon  

1689

E. ANDfinity

给出 n 个非负整数 aiij 连边当且仅当 aiaj0,这里的 是位与运算。

一次,你可以执行两种操作的一种:

选择一个 ai,让其 +1

选择一个为正的 ai,让其 1

求让整个图连通,所需要的最少操作数。

2n2000,0ai<230

Hint1

首先,将 ai=0 的位置加上 1

注意到任意两个奇数都连通。

Hint2

考虑偶数,对偶数减一性质比较良好:这样会在 lowbit 之后的位都产生 1,且它就和奇数连起来了。

Hint3

试说明:此时 ans2

Solution

挺有意思的题,vp被前面的题搞心态差了一点时间...

注意到若连通,则不会有 0 存在。因此对于所有 ai=0 的位置先加一,这样全部为正整数。

考虑奇数之间由于最低位置存在 1 必定连通;对于偶数,我们发现,当它加上 1 或减 1 以后,也会和奇数连通。

偶数的 +1 是好考虑的,而减一,就是找到 lowbit 并置零,将所有更低的位置为 1

所以如果减一,我们有个想法是找到 lowbit 最大的偶数排序,这样就能顺带把 lowbit 更小的位置连上。

但是如果有多个 lowbit 最大的这样就寄了。

然后发现如果还有 lowbit 最大的,把它 +1,这样就满足条件了。

所以关键结论是此时的 ans2,因此我们只要检查是否能让 ans=1 即可。

首先我们发现可以 O(nlogw) 的去检查一个数组是否合法,所以暴力枚举修改的哪个位置,就可以 O(n2logw) 地做了。

P.S. 这题和 CF1553G 都一样,只要看出 ans2 就随便做了。

记录


1693

C. Keshi in Search of AmShZ

给出一张 nm 边有向图,可能有重边。初始,角色在点 1,目标是走到点 n

每天,可以执行下面两种操作的一种,直到角色走到 n 为止:

  • 选择任意一条边,删去。

  • 假设角色在点 u,此时随机游走到一个点 v,满足 uv 有一条未被删的连边。

问最坏情况下,从 1n 最少需要多少天。

n,m2×105

Hint1 倒着设计 dp!
Hint2 观察到未确定的 dp 值里,最小的永远不会再被更新。

考虑类 dij 的方式确定 dp。

Solution
  1. 图论是大弱项

  2. 从一开始我的思考方式就出现了问题

f(u) 是从点 u 开始,最少需要多少天才能到达点 v。显然 f(1) 即为所求。

考虑转移,f(u)=f(v)+1,其中 v 应该是一个最糟糕的点。换言之如果 ujuk 有连边,且 f(k)>f(j),则要么我们删去 ik 的连边,否则在最坏情况下我们必须从 i 走到 k 而不是从 i 走到 j

所以 f(u)=min{f(v)+cnt},其中 cnt 是所有 u 能一步走到的点 x 中,f(x)>f(v) 的。

注意到这个图并不是 dag,所以不能直接转移 dp。

图上 dp 的另一种实现是最短路。

因为 cnt0 所以这个 dp 的转移是单调不减的,换言之我们可以用类 dijkstra 的方法去迭代求 f:当前最小的,未被标记的 f(v) 一定不会变得更小了,所以取出 f(v) 并且标记,然后去进行对 u 的转移。

时间复杂度 O(nlogn)

记录

P.S. 很多时候图论问题都应该是设计一个“当前位置到终点的最短路”而不是“起始位置到当前位置的最短路”。一个典型的例子就是绝大部分期望 dp 的状态设计(这类期望 dp 本质上也是一个 dag 游走问题)。

在本题,为何我们不能设 f(i) 代表 1i 最坏情况下的最少天数?因为如果 f(k)>f(j),我们并不能保证,ik 就会比 ij 来得更差(比如若 j 无法走到 n,那 ik 反而会更优秀)。而倒着设计显然不会出现此类问题。

这道题虽然简单,但是很有思考价值。

--------

D. Decinc Dividing

若一个序列能恰好拆成一个上升子序列和一个下降子序列(可空),则称其为好的。

给出一个 n 排列 p,询问 p 的好的子段的个数。

n2×105


非常牛逼的一道题啊。

首先本题的 check 已经是众所周知的一道题了:CF1144G。

事实上关于序列(排列)拆分成一个上升子序列和一个下降子序列,最简便的方法也是 dp:设 f(i)1i,其中第 i 个元素放入了上升子序列,此时下降子序列结尾的最大值;以及 g(i) 表示第 i 个元素放入了下降子序列,此时上升子序列结尾的最小值。这样有一个 O(n) 的 dp 去实现 check。

在本题中,设 fl(i)gl(i) 代表从 l 位置开始,然后第 i 个放入了上升/下降子序列,此时对应序列结尾的最优秀值。如果 f(i)= 说明此时下降序列可空,如果 f(i)= 则说明不能把 i 放进上升子序列。显然 [l,r] 合法当且仅当 fl(r)= 以及 gl(r)= 不同时成立。

结论:如果 i 确定,则 fl(i) 只有 4 种可能取值。且随着 l 的上升而上升。

证明:首先 是肯定存在的。然后假设存在一个最大的 j<i 使得 pj>pj+1,则首先 pjpj+1 必定有至少一个划分进下降子序列。且 pj>pj+1<pj+2<...pi。要么 pj 划分进了下降子序列且 pj+1 划分进了上升子序列,那么我们显然可以把 j+2i 全部划分入上升子序列;或者 pj+1 划分进了下降子序列,此时 pj+2 必须划分进上升子序列,由此剩余的也肯定可以划分进上升子序列。

显然对于 g 有类似结论。

所以我们降序(或者升序)枚举 l 皆可,然后暴力从 dp(i) 更新到 dp(i+1),如果更新前后的 dp(i+1) 没有任何变化,我们就停止更新。

这样,每进行一次更新,意味着至少一个 f 或者 g 发生了变化,而总变化次数是 O(n) 级别的。因此时间复杂度同样是 O(n)

记录


E. Outermost Maximums

有一个长度为 n+2 的序列 a,其中 a0=an+1=0 已确定。现在给你 a1an 的值。

你可以执行任意多次两种操作的一种,使得 a1an 都变为 0

  • 找到 a 最左边的最大值位置 x,并令 ax=maxi=0x1ai

  • 找到 a 最右边的最大值位置 y,并令 ay=maxi=y+1n+1ai

试找出最少操作步数,n2×105,0ain


首先我们肯定会不断操作最大值并让其变为更小的值。

所以假设初始最大值位置为 p1,p2,...,pk。显然 p 的一段前缀是用操作 1,剩下的一部分后缀是用操作 2

li 表示 i 左边最大的 <ai 的位置,同理有 ri。那么 lp1,lp2,...,lpn 单调上升,rp1,rp2,...,rpn 单调下降。

所以我们可以保证一轮变化后 api 变成了 min{alpi,arpi}。显然这是最优秀的。

容易发现按照这样的变化方式,实际上每个位置是独立的。换言之,我们把问题改写成,给出一个和 a 完全一致的序列 b,然后枚举 i1n。每次令 bi=min{blpi,brpi} 且重新更新 li,ri 直到 bi=0 为止。问变化次数和。

到这里暴力模拟是可以做到 O(n2) 级别的,仍然不够优秀。下面是神来之笔:

我们研究某个时刻的 i:考虑值域。设 f(x,0)=1 当且仅当有一个 j<i 满足 bj=x,同理 f(x,1)=1 当且仅当有一个 ji 满足 bj=x

然后,我们初始在 bi 位置,然后不断向前走,每次走到最近的 f(x,0)=1f(x,1)=1 的位置(显然我们会走比较远的那个,但是在这里没有什么用),直到走到 0 位置。

dp[l,r,0/1,0/1] 是从 r 外面进入,走出 l 的最少步数。两个 0/1 分别代表我们进来的时候是想走到 f(x,0)=1 还是 f(x,1)=1,以及出去的时候是想走到 f(x,0)=1 还是 f(x,1)=1

容易发现这个 dp 是容易 O(1) 合并的。而 i 增加的过程就是修改了 dp[ai,ai],每次求的是 dp[0,ai1]。所以用线段树维护这个结构就行了。

虽然说起来简单,但这个做法非常的高妙,非常的有启发意义。

时间复杂度 O(nlogn)

记录

P.S. 这题没有独立想到最后的 DS 优化部分,思考了一下,发现这部分和之前做过的一道 CF 题 MCMF(当时也是想到 n2 没有得出进一步的 DS 优化)存在一类共同点:

就是我们要对数列的每个位置都去执行一个类似的操作并求结果,而这个操作是依赖于数列本身的。那这个时候我们发现单个的考虑其实往往没有什么优秀性质,但我们可以用一些 DS 去维护,为什么可以 DS,是因为 ii+1 的时候,由于你的答案只依赖于数列本身,而指针移动一位造成的变化往往很小。所以我们可以很快地处理这些变化,然后就变成一些简单的 DS 了。


1695

D2. Tree Queries(Hard Version)

给出一颗 n 点的树,找到最小的 k,满足:

存在一个点集 x1,x2,...,xk,然后对于树上每个点 x,设 x 到这 k 个点的最短路数组为 Dx=d(x,x1),d(x,x2),...,d(x,xk)。不存在两个点 x,y 使得 Dx=Dy

n2×105


很牛逼的 div2 D。

显然若点集中有两点 (x,y),则路径 (x,y) 上的所有点不用考虑,它们的最短路数组一定唯一。

所以假设点集已经确定,对于点集中任意两点 (x,y),把路径 (x,y) 上的点全部染色,则答案合法等价于没有一个染色点有 >1 个的未染色相邻节点。

所以容易想到设 f(u) 代表子树 u 合法的最小代价,设 u 的所有儿子中有 x 个儿子的 f(v)=0(实际上这意味着 subtree(v) 是一条链),则有:

f(u)=f(v)+max{x1,0}

但这其实是有问题的。原因在于假设 u 是二叉的,你只在一颗子树里找点加入点集是不够的,要么 u 子树外(或者 u 本身)还得来一个点,要么 u 要是三叉往上的,这样 u 点才会被染色到。

由此得出两种思路:

  1. n1 的时候必然有一个点被染色,暴力枚举它,作为树根,执行上面的 dp,然后 +1 最后取 min。直接暴力是 n2 的(可以通过 D1),我们发现这个 dp 容易换根优化,时间复杂度 O(n)

  2. 随便找一个三叉往上的点定根,然后跑一遍 dp 就行了。如果找不到,说明是个链。

记录


1698

F. Equal Reversal

给出两个长度为 n 的序列 a,b,你需要在不超过 n2 次操作内将 a 变为 b。一次操作指选定一个区间 [l,r] 满足 al=ar 并反转 a[l,r]

n500


神题。

首先假设在 aiai+1 之间连一条无向边,则不管怎么操作,这个图 G 不会发生改变。(本质上是相邻元素对集合不会改变)。

而我们从 a1 这个点开始走,每次沿着 aiai+1 走,可以发现走出了 G 的一个欧拉路。

事实上 G 还有别的从 a1 开始的欧拉路。显然一条欧拉路唯一对应了一个新的序列 a,可以证明的是每个 a 都可以由原序列 a 通过若干次反转得到。

我们先来研究反转在图论上的意义。反转确实不会更改图 G 的形态,但他会更改我们的欧拉路径。具体而言,是选择一个环,并且将定向取反,访问顺序也取反。即本来是 alal+1...ar1al,更改为 alar1...al+1al

现在来证明运用这个操作,总能让两条 a1 开始的欧拉路径重合。

我们采用归纳+反证的形式,即假设 axbx 处是第一处不同的地方(显然 1<x<n)。设 u=ax1,v1=ax,v2=bx

由于走的都是欧拉路径,所以在 a 的走法里,<u,v2> 这条边还是要走的;在 b 的走法里,<u,v1> 这条边还是要走的。这实际上告诉我们这两条边都存在于环上。

  1. 假设在 a 的走法中,走的是 v2u。此时 uv1...v2u 就是一个环。反转它,则先走 uv2

  2. 假设在 a 的走法中,走的是 uv2。此时路径形态形如 uv1...u...uv2...u...。反转 <u,v2> 在的那个环,则变成了 v2u,回到第一种情况。

所以两条欧拉路径始终能完成重合。

放到原序列,其实两种讨论,对应了构造的两种情况。首先,总的思路是,从前往后一位位构造。当第 i 位不同的时候,必定满足下面两种情况之一:

  1. 存在 j>iaj=ai1,aj1=bi,此时直接翻转 [i1,j] 即可。

  2. 存在 jiaj=ai1,aj+1=bi,且存在某个区间 [l,r] 满足 li1[j,j+1][l,r],此时翻转 [l,r],回到情况 1.

我们发现其实与图论上的两种情况完美契合。

时间复杂度 O(n3)。操作数上界 2×(n2)

记录


G. Long Binary String

给出一个长度为 ,初始全为 0 的串 t,以及一个 01S。你可以执行任意次操作,每次把 S 放在 t 的任意位置并将相应位置异或 S。问是否能让最后的 t 恰好有两个 1,若有,输出字典序最小的 t 中,1 的两个位置。

|S|35


这是多项式题是我没想到的...

首先忽略原串 S 的前导零,然后将其看成一个系数 <2 的幂级数 P(x)

然后我们类似的,对操作序列定义一个幂级数 Q(x),当我们有一次操作,S 的首位和第 n 位对齐了的时候,那么 [xn]Q(x)=1。这样,我们得到的最后的串显然可以用 P(x)Q(x) 表示,这里我们需要重新改写多项式乘法,将其改为在异或意义下。(可以看成,就是常规的多项式乘法,最后把系数全部模 2 的一个过程。)

显然第一个位置一定是 1,而第二个为 1 的位置是不确定的,换言之有方程 xk+1=P(x)Q(x),其中 k 是一个正整数,我们希望它尽可能小。

注意到 Q(x) 是任意的,所以原式等价于同余方程 xkP(x)1(modP(x)),然后就是多项式版本的一个 bsgs 过程。因为你注意到这里 k 的上界就是 235(考虑模 p 的剩余系大小)。

我们可以把系数压进一个 long long 来存。注意到乘法的时候会爆精度,所以乘法的时候用一个 __int128 缓冲即可。

时间复杂度 O(|S|plogp),其中 p=2|S|

记录


1699

E. Three Days Grace

给出一个多重集 S,其中的元素都在 [1,m] 之间,你可以执行任意多次操作。每次操作选出多重集的一个元素 d,然后找到两个大于 1 的数 u,v 使得 u×v=d,最后删除 d,加入 u,v

问可能的,max{S}min{S} 的最小值。

n106,m5×106


考虑枚举最小值 minn,然后设 dp(x)x 拆分成若干 minn 的数之积,且最大值的最小可能值。

首先考虑维护 dp,发现在 minn 移动的过程中,假设当前移动到了 i,那么显然只有 i 的倍数的 dp 才会变化。

也就是说 dp 的总计算次数是 O(mlnm) 的,但是每次重新计算 dp 是花费 O(d) 的时间的,显然不能通过,这比 O(mln2m) 实质上要慢很多。

如果我们是增大 minn,那么是不好维护滴。注意到我们如果是降序枚举 minn,那么 dp 值只可能变得越来越小,所以我们每次更新 i×j 的时候,直接把 max{dp(i),dp(j)} 和原有的取 min 即可。

现在我们可以 O(mlnm) 的总时间维护所有 dp 值了。我们还需要知道,dp(a1),dp(a2),...,dp(an) 的动态最大值。一个朴素的想法是维护一个多重集,每次修改 dp(ai) 之前删了,修改后把新的 dp 值放进去。但这样复杂度就不能保证是 O(mlnm) 了。还是注意到 dp 值永远在下降,此时有个套路,就是维护一个桶,维护一个指针表示当前最大值。如果桶里指针位置为空,那么之后的时刻这个位置不可能再放入数了(因为最大值永远在下降),此时直接让指针 1 知道指向的桶的位置非 0 即可。这样这个过程均摊下来是 O(m) 的。于是总时间复杂度 O(mlnm),空间复杂度 O(m)

事实上枚举 maxn 有对称做法,但我们必须每次寻找约数,这是比较难实现的。另外,枚举 minn 的做法并不会跑满,因为枚举 i×j 的时候,ji 才有意义,那就意味着 im 的时候才会发生 dp 的更新。

记录


1700

E. Serega the Pirate

给出一个 n×m 的矩阵 a,满足 1ai,jn×m 且两两不同。称矩阵 a 是合法的,当且仅当存在一条四联通路径,从 1 所在位置出发,n×m 所在位置结束,且满足:对于任意 i2i 第一次出现晚于 i1 第一次出现。

定义一次操作是交换 a 中的两个元素位置。

如果 a 是合法的,则输出 0。如果 a 可以经过恰好一次操作变得合法,输出 1 后,再输出可能的操作种数。否则输出 2

n×m4×105


首先这个合法就等价于每个非 1 位置都至少有一个相邻的小于它的位置。所以 0 是容易判的。我们称满足这样性质的位置为合法位置。

然后注意到一次交换最多让 4 个位置从不合法变为合法。所以我们在不合法位置大于 4 的时候直接输出 2

否则,交换的两个位置,必定有一个位置,它要么是不合法位置,要么与合法位置相邻。这样的位置最多有 4×5=20 个。

所以在 O(nm) 的时间内可以确定所有点对,带 20 的常数。checkO(1) 的,这里常数不能太大,因为本题的时间限制比较严格。

记录


F. Puzzle

给出两个 2×n01 矩阵 A,B。定义一次操作是交换 A 中相邻两个位置的值。问把 A 变为 B 的最小操作数,或报告无解。

n2×105


很精妙的题,有 atc 的感觉。

首先无解的条件就是 A,B1 的个数不相等。我们接下来探讨有解的情况。

因为一次操作必定牵扯到一个 1,所以我们可以这样更改题意:允许 1 在中途重叠,一次操作定义为选择一个 1 并移动。我们容易发现这个问题的答案和原问题是等价的。

这样有一个什么好处?就是说我们不用考虑 11 这种操作的麻烦了(从交换的角度来看,它是无意义的)。我们可以直接把原问题变成将 AB 中的 1 进行一一匹配,边权为曼哈顿距离,求权最小的完美匹配。这个转化是特殊的,它只在 0/1 的矩阵上成立。

另一个角度是从 1×n 的情况入手。显然我们会把两个矩阵中的 1 排序,然后一一配对。事实上,这个策略有一个更形式化的表述:i=1n|saisbi|,其中 saa1 的前缀和,sb 同理。记 di=saisbi

现在让我们把视角放到 2×n 的矩阵中。我们注意到根据先前的转化,所有的上下操作都可以放到开头完成。注意到一次上下交换的操作实质上是把一行的 din 全部减一,另外一行的 din 全部加一。

我们从前往后扫,注意到若两行 di 同号则执行上下交换不优;若异号,假设第一次出现,则此时绝对值较小的是 1。我们把正的减去一,负的加上一,这样答案减小了一。同时我们发现按照这样的调整,此时变为了同号的情况。换言之按照这个贪心,每次碰到异号,绝对值较小的值一定是 1。所以总能实现一次上下操作(如果不能实现,说明为 0,那值就不会变化,与“第一次”异号矛盾)。所以这个 O(n) 的贪心就能解决问题。

记录

posted on   Cry_For_theMoon  阅读(162)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
 
点击右上角即可分享
微信分享提示