24 暑假 diary(MX 盖世计划 B 班集训后半段)

7.28

前些日子在上 hb 的课,打算 29 号开始打下 MX 的。

那今天就摆摆摆了,就随手写了几道题。

不配打 A 班,在 B 班垫底挺好的。

7.29

上午模拟赛,打得像个唐氏。

期望得分:30+60+10+10=110

实际得分:30+35+10+10=85

倒数前十,第一天就垫底,rp++ 了这下,但我真他妈不会啊,被嘲讽了/ll/ll。

然后就补题补了一下午+大半晚,谁叫你一题不会的来着。

A#

考虑把平方内的式子化成 2m2i=1nmin(Ai,Bi)

枚举 min(Ai,Bi)=s,那么此时序列的贡献就是 (2m2s)2,对这种序列计数就可以了。

首先先对 s 隔板一下,把 s 分成 n 份且允许有空,方案是 (n+s1s)

AiBi 之间的关系分成 Ai>BiAi=BiAi<Bi 三种,枚举第一种位置有 x 个。

首先你要先在 A 里选出来 x 个,有 (nx) 系数,然后你还要把 ms 的和摊下来对吧,乘上 (ms1x1)

最后就是你需要再把 ms 的和摊在 Bnx 个位置上,是 (ms+nx1ms)

复杂度是 O(nm) 的。

我草我场上真不会啊??我草我场上真不会啊??我草我场上真不会啊??我草我场上真不会啊??

B#

考虑暴力做法直接设 fi,j 表示 i 时刻 j 点的期望,对时间扫过去暴力转移即可得到 60 分。

显然地会发现这个 dp 可以写成矩阵乘法的形式,以为自己会了突然想起来输出的是异或和。

如果输出的是和可以直接倍增预处理转移矩阵的 2k 然后做 m 次向量乘矩阵的快速幂即可(NOI2020D1T1),但是既然它让你输出的是异或和说明他肯定是要你每个时刻挨个求一遍的,所以应该放弃倍增这种做法。

考虑平衡复杂度,设置一个阈值 B 并每 B 个时刻一起做,处理出转移矩阵 Mk,k[1,B],那么假设当前是在时刻 t,把 f 的一行看作是向量的话,时刻 t+k 的答案就是这个向量乘上 Mk 的第 n 项,而观察到求向量乘矩阵的某一项是 O(n) 的,所以这个做法很可能是可行的。

我们直接算一下看看,预处理 Mk 复杂度是 O(n3B) 的,算每个时刻的答案是 O(TBnT)=O(nT) 的,同时你最多连续算 B 次所以你需要完整乘上转移矩阵 TB 次,这里是 O(TBn2) 的。观察一下可以直接取 B=175,然后过了。

理论最优是取 B=Tn

C#

相比之下没那么神经的一道题,但是场上这题我是最不会的/cy。

(xi,yi) 为第一轮走到第 i 步时走到的位置,容易发现走一轮起点到终点的坐标变化量是不变的,记为 dxdy

同时也容易观察到,第 k 轮时走到第 i 步的坐标和第 k1 轮时走到第 i 步的坐标变化量也是 dxdy,因为中间也正好差了一整轮,更形式地,第 k 轮第 i 步的坐标就是 (xi+(k1)dx,yi+(k1)dy)

所以说能走到的点在若干条以 dydx 为斜率的直线上,那你直接把第一轮的 |S| 个点按照所在的直线分类,每条直线内按照原来的横坐标排序根据差值就能算了。

复杂度大概是 O(|S|log|S|)

D#

你也是道魔怔题。

考虑分块,先暴力处理出来初始的答案,去从区间覆盖这种操作入手。

修改时,散块内直接暴力改,考虑整块。因为块内的 bi 是永远不会变的,所以设我们要把当前块修改成 x,那么只需要求出来最小的 xbigcd2(x,bi) 即可,如果知道 ci 表示块内为 i 的倍数的 b 的最小值,那么可以枚举 x 的因数 d,用 dcdd2=cdd 来更新答案。综上我们有了一个基于预处理的做法:先处理出来 ci,j 表示第 i 个块内 j 的倍数的最小值,再根据刚才做法预处理出来 fi,j 表示第 i 个块被覆盖成 j 的块内答案,修改时散块暴力整块直接查表打标记即可,查询是容易的。

有个很神经的地方是,修改时对散块暴力求 gcd 多个 logV 好像过不太去,要贺一个 O(V)O(1) 的快速 gcd……

块长直接取 B=n 就能过,但是复杂度的瓶颈其实在预处理上,直接实现容易做到 O(nBVlogV),但是这个有点卡常,可以用类似埃筛的方式做到 O(nBVloglogV)

我卡了一下午常/oh我卡了一下午常/oh我卡了一下午常/oh我卡了一下午常/oh。

7.30

训练赛,只会一道题,真给我糖丸了。

我觉得很合理,剩下的确实不像是我能做出来的。

训练赛的题解就写得简略点了,因为我懒。

A#

考虑初始局面 ai 和最终局面 bi,分别设 siti 表示它们的前缀和序列,那么最小移动次数就是 |siti|

所以我们轻易地刻画出了移动次数的限制,直接 dp 即可,设 fi,j,k 表示前 i 个数当前的前缀和为 j 且最后一个填了 k 的最小代价。

暴力转移是四方的,维护个后缀 min 容易优化到三方。

B#

考虑设 fu 表示 ut 字典序最小的串,比较出字典序最小的本质其实是找到 lcp 然后再比下一位。

lcp 可以考虑哈希+二分,而这题是在 DAG 上且每个点都需要维护。但是观察到每个点的哈希值其实是一种继承关系,也就是找字典序最小的后继继承过来再在开头加字符,所以说容易想到主席树维护哈希。比较时直接二分套主席树即可,因为这题特殊的插入方式感觉不太能在主席树上二分。

唉这不是那道 The Classic Problem 吗。

直接做是 O(nlog2n) 的。

C#

考虑单个 k 的做法,那不是直接赛道修建,每个点维护最长的未匹配的链的长度,直接贪心选最长的两个儿子判断能否合并。

答案显然只有 O(n) 种取值,而且随着 k 的增加答案肯定是单调不升的,所以说答案其实是分段的。

直接二分出每个段就好了,复杂度 O(nnlogn)

D#

不知道为什么放在这里的唐氏题。

F#

考虑一个结点被放了棋子对于局面的影响。假如只有一个棋子,那么按照最优方式移动先手的移动次数肯定多于后手,可以使用最优策略下的步数来判断输赢。设 fu 表示棋子在 u 时先手能比后手多走几步,如果 u 是先手的点有 fu=maxfv+1,是后手的点就是 fu=minfv1

那题目让我们计数数的是什么东西呢?容易发现所有的棋子之间其实是很独立的,有多个棋子时,只要这些棋子总共能让先手走的步数大于后手,就一定是合法的局面,所以就相当于是求有多少个子集的 f 之和大于 0,直接做背包即可,复杂度 O(n3)

7.31

模拟赛,这场打得还可以。

期望得分:[70,100]+15+100+15=[200,230]

实际得分:100+15+100+15=230

但是 B 和 D 一点不会做其实挺唐的。

A#

先考察下这个变换操作和序列有什么特殊性质,考察了一个小时结论是啥都没有。

场上很慌啊,感觉一点不会,直接写了个爆搜加了点剪枝,看所有样例都跑出来了就扔了,然后赛后一看过了。

事实上爆搜的复杂度就是挺对的,我们考察下搜索树的性质。

显然遇到 1 怎么变都是 1,这个特殊判掉,然后我们搜索树的每个点至少都有 2 个儿子,我们要求的其实就是前 m 个叶子结点之和,而一棵树如果满足有儿子的点儿子个数至少为 2,那么非叶子结点的个数一定是小于叶子结点个数的,那么我们的复杂度其实就是 O(m×) 的。

考虑加速搜索时枚举因数的过程,容易发现枚举的一定是开始时 x 的因数,提前预处理排序即可剪枝。

加上这些就能直接过了,不好评价的题。

B#

场上一点不会,挺唐的,但我感觉这题确实挺牛的,这里参照一些 zxb 讲解时的思路,我觉得很 educational。

首先接到这个题我们发现这个排列是完全随机的,序列有什么我们根本不知道,我们不太喜欢。但是同时也是由于排列是任意填的,这也启发了我们题目可能有很强的对称性,也就是说有很多的方案或者位置其实是等价的,我们可以试图通过较少的信息来描述出这些等价的东西。

具体地,我们注意到函数在执行完毕后,我们其实只关心两个信息:lcntrcnt,分别表示累加到和里的数中有多少个小于/大于最后的数。显然每条路径的 lcntrcnt 是可以轻松确定下来的,我们发现对于所有 lcntrcnt 都相等的路径它们的限制其实是完全一样的,所以 lcntrcnt 就能用来区分真正本质不同的路径。而我们又发现因为递归的层数最多是 O(logn) 的,所以 lctcnt 都不超过 logn,最多只有 O(log2n) 种状态,这样我们就做到了用较少的信息描述出全部路径。

f(lcnt,rcnt,x) 表示当前查询的是 x,一条状态为 (lcnt,rcnt) 的路径的贡献,f 的计算我们考虑枚举最后一个返回的数。

设返回的数为 y,如果 y=x 贡献就是:

x(x1lcnt)lcnt!(nxrcnt)rcnt!

对于 y<x 的部分贡献就是:

y<xy(x2lcnt)lcnt!(nxrcnt)rcnt!

同理对于 y>x 的部分就是:

y>xy(x1lcnt)lcnt!(nx1rcnt)rcnt!

统一再乘上一个 (nlcntrcnt1)!,因为剩下的数可以随意排列。

显然 f 是可以做到 O(1) 计算的,所以每次询问直接枚举 lcnt,rcnt 计算 f 即可,需要提前处理出每种 (lcnt,rcnt) 的路径有几个。

时间复杂度 O(mlog2n)

C#

感觉之前吴爸讲过一个类似的建图,所以场上过了(笑)。

首先考虑暴力,若 ai&aj=0 我们直接连边 ij,考察这张图有什么性质。

不难发现对于每个连通块,我们一定能将这个连通块内对应的位置直接排序,因为我们可以实现任意交换。

但是这么做边数是 O(n2) 的,而且我暂时不知道有什么其他 O(n2) 做法,所以考虑直接对这个进行优化。

注意到 ai&aj=0 等价于 aiaj 补集的子集,反之亦然,而且对于原图我们其实并不关心它的具体形态,我们只在意它的连通性是如何的,所以我们可以考虑这么建图(以下为有向边):

  • 对于每个下标 i,将 i 连向 ai 的补集,将 ai 连向 i
  • 对于每个 02201 的数,向其去掉一个 1 的子集连边。

注意要建 220 个虚点来表示每个取值,下标要另开 n 个点来表示。

容易发现这样每对满足 ai&aj=0 的点对之间会形成一个强连通环,那原图的一个连通块其实就对应了这张图的一个 SCC。

发现边数是 220×10+2n 的,直接跑强连通分量即可,可以认为复杂度是 O(nlogn) 的。

D#

其实是个简单题,没绷住。

首先直接计算无从下手啊,那肯定是先拆每个点对的贡献,不然根本算不了。

K=(rili+1)ki=rili+1dii 号点深度,我们枚举每种颜色 c,答案其实就是:

c=1ni=1,c[li,ri]nj=i+1,c[lj,rj]nKkikj(di+dj2dlca)

K 的常数提出来,省略一些中间化简的过程,答案其实就是(以下省略颜色的条件):

(i=1n1kij=i+1ndjkj)+(i=1ndikij=i+1n1kj)+(i=1n1kij=i+1n2dlcakj)

对于颜色的限制,我们考虑直接对颜色扫描线,那么只需要维护一个加点和删点的操作。加入或删除点时前两个式子都是很好增量维护的,关键在于第三个式子含有一个 lca 的深度不好解决。

处理方式是,考虑 lca 的深度其实就是 ij 两个点的公共祖先个数,所以如果我们把 j 到根的路径加 1,那么 i 到根的路径之和其实就是 i,j 之间 lca 的深度,求和同理。对于这题带个 1kj 的系数,那就直接到根的路径加上 1kj 就好了。需要支持路径加路径查询,需要上一个树剖维护。因此第三个式子同样可以对颜色扫描线增量维护。

那其实已经做完了,复杂度 O(nlog2n)。其实可以建出来点分树做到 O(nlogn) 的,但是我没听懂。

8.1

睡得很舒服。训练?真的不熟。

算了还是点开看看题,怎么全是 DS。。。

A 是那道 T-shirt,B 简单题,CD 根号题,懒得写了,开摆。

8.2

好耶,又是模拟赛,打得还可以吧。

期望得分:70+100+30+30=230

实际得分:90+100+30+50=270

逆天反向挂分。

A#

肯定先拆线性性吧!对于血量为 x 的怪,每次分出来一个蓝量小于 x 的段,都会有 1n 的贡献。

所以先开桶前缀和预处理,这样我们很容易得到分出来一个蓝量为 x 的段的贡献,记它为 fx

暴力 dp 考虑设 dpi,j 表示已经分了 i 段当前蓝量和为 j,枚举 k<jdpi1,jk+fk 更新即可,直接实现是 O(nm2)

考虑优化,容易发现每层转移之间相当于和 f 做了 (max,+) 卷积。

所以定义乘法为 (max,+) 卷积,我们要求的其实就是 fn,快速幂即可,O(m2logn)

B#

什么唐氏题,还能放 T2 的。

考虑每次询问我们该怎么走,每个点的出边我们按照指向的点的编号排序,那么我们每次移动肯定选第一条指向可以到达终点的边。

这个暴力移动直接告诉了我们,如果知道了终点在哪每个点要怎么走是唯一确定下来的。

所以我们可以枚举终点 t,求出每个点会怎么走,按照这个走法建出来一张新图,考察这张新图的性质。

新图可能会存在环,如果一个点到终点之间有环点那序列肯定是无穷大的长度,否则我们直接找出这个图上的路径上的第 k 个点就行了。

因为每个点出度至多为 1,也就是跳法固定,所以可以直接倍增回答询问,同时这也方便了我们判环:如果走 n1 步走不到终点那就说明会经过环,直接判掉。

每个终点都预处理一遍即可,O(n2logn+qlogk)

C#

手玩一下容易发现策略:每次最靠左的清零之前来回横跳,直接模拟是 O(nq) 的。

考虑如何维护这个过程,设 bi=aibi1,含义为 i 会被反复经过几次,知道 bi 之后回答询问是容易的,显然要求任意 bi 非负,其次就是要求 br=0 之类的,这些会跟区间长度的奇偶性挂钩,单独讨论即可,只需要知道如何维护 bi

对于区间 [l,r]x[l,r] 内和 l 奇偶性相同的 bi 会加上 x,否则会减去 x。同时对于 (r,n] 来说,如果 rl+1 为奇数则还需要再给与 l 奇偶性相同的位置加 x、不同的减 x。以上得到了 bi 的维护方法,对奇偶下标分别开线段树维护即可。

所以做到了 O(qlogn)

D#

什么魔怔题,flow 太魔怔。

因为答案是分式的形式,考虑 01 分数规划,二分答案 x,判断是否存在集合 S 有:

(iSai)2iSai2x0

集合的形式未免太丑了,我们设 pi,j 表示 i 号点和 j 号点是否同时被选,把式子写成:

i=1nj=i+1npi,j(2[ij]aiaj)i=1npi,iai2x>0

这个可以按照最大权闭合子图的模型建模跑最小割判断,而且还有严格的复杂度上界 O(n4logϵ)

具体地,这个相当于是一张有 n2 个点的图(对应所有 pi,j),对于 ij 的点有正的点权,i=j 的点有负点权,且要求对于每对 (i,j) 如果选了 pi,j 那么 pi,ipj,j 必须要选,同时原图的 (u,v) 边也表示了选了 pu,upv,v 也要选。这是相当清晰的最大闭合权子图模型。

8.3

什么唐氏模拟赛。

期望得分:100+100+100+50=350

实际得分:100+100+100+50=350

A#

前三题最难的题吧。

考察操作的本质,选两个互质的数代价是显然的,假设选择的数 x,y 存在质因子 pe1pe2,如果 e1>e2 那么最后两个数 p 的次数会互换,换句话说就是每次操作会把次数小的扔到一边,次数大的扔到另一边。

那就尝试每个质因子分开做,我们把质因子按次幂排序,尽可能把大的仍在一个数就好了。

复杂度肯定能过,上界是 7×nlogn

B#

未免有点太典了吧。

撤销操作先放在一边,把修改操作搞明白之后撤销可以直接暴力做逆操作,(1)d 也先不管。

按照相对深度加等差数列,我们肯定是要转成绝对深度的,具体地把贡献写成 a+b(depvdepu),拆成 a+b×depvb×depu,那么 ab×depu 可以视为对子树内加一个常数,剩下的就是子树内点 v 加上 b×depv,这些都是好维护的。

因此我们按照 dfs 序把修改操作扔到 set 里,每次撤销直接把子树内的取出来逆向操作即可。

对于 (1)d,假设我们要在 x 处修改/查询,把修改/查询的值直接乘上 (1)depx,容易发现这样贡献是对的。

时间复杂度 O(mlogn)

C#

未免有点太唐了吧。

考虑扔掉 k 个关键点的限制,直接对邻接矩阵跑矩阵快速幂即可。

考虑加上 k 个关键点的限制,容斥一下,枚举 S 并钦定 S 内的关键点不走,邻接矩阵上扣掉被钦定的点然后再跑矩阵快速幂即可,容斥系数是 (1)|S|

时间复杂度 O(2kn3logd)

D#

线段树分治,懒得写了。

8.4

休息。

8.5

答辩模拟赛,不想补了。

努力钻研了一下 wqs 二分,略有理解,抽空会专门总结。

8.6

抽象训练,三个博弈一个数数两个 DS。

懒得写了。

8.7

搬了云浅出的一场模拟赛,打得很一般,T3 的平方没拿到糖丸了。

期望得分:100+100+15+25=240

实际得分:100+100+0+25=225

云浅怎么在 T4 放 *3200 的 dp of dp。

A#

等价于分别在 ab 中选一个区间,使得两个区间内 1 的个数相乘为 k

如果要求一个序列内有几个区间 1 的个数为 x,直接前缀和+桶可以线性统计。

现在我们就直接枚举 k 的因数在 ab 里统计就好了。

时间复杂度 O(nd(k)),怎么还他妈有人写 NTT 的。

B#

答案显然具有单调性,先二分答案 mid

先考虑树的情况,为了开始连通每条边起始时间肯定是 1,那么所有边权小于 mid 的都要补上,判断代价和是否不超过 L 即可。

对于基环树,考虑把环边拉出来,容易归纳证明肯定要把环上权值最小的边在开始时刻断开,次小的边结束时接上。

此时相当于环上最小和次小权值的边合并,然后就等价于树上了,没有区别。

时间复杂度 O(nlogn)

C#

我草为啥我场上一点不会做/ll/ll。

先拆点对贡献。先拆点对贡献。先拆点对贡献。先拆点对贡献。先拆点对贡献。先拆点对贡献。先拆点对贡献。先拆点对贡献。

我们考虑枚举点对 (i,j),考察这个点对之间路径的性质。

我们称 S 内的点为关键点,我们发现最优且限制最弱的走法一定是,从 i 一步步走到 i 右边第一个关键点,然后从这个关键点跳到 j 左边的第一个关键点,再一步步走到 j。也就是 (i,j) 有贡献的充要条件就是 i关键点关键点j 之间的点没被删除。

我们假设这些点一共有 x 个,我们枚举在排列的第几项被统计。贡献就是:

k=0nx(nxk)k!(nk)!

求和的东西全都和 k 有关,不好化简,我们把组合数拆开:

=k=0nx(nx)!k!(nxk)!k!(nk)!=k=0nx(nx)!(nk)!(nxk)!=k=0nx(nk)!x!(nxk)!(nx)!x!=(nx)!x!k=0nx(nkx)=(nx)!x!(n+1x+1)

所以对于每对需要经过 x 个点的点对,贡献就是上面的式子,接下来考虑统计 cx 表示经过 x 个点的点对有几个。

注意到关键点将原序列分成了若干段,我们枚举两个段,假设长度分别为 a,ba<b,那么贡献形如:

  • i[1,a],j[1,b]ci+jci+j+1

我们分析下,当 x[2,a] 的时候,相当于给 c 区间加一个等差数列;当 x(a,b) 的时候,贡献为定值 a;当 x[b,a+b] 的时候,贡献也是区间加一个等差数列。区间加等差数列可以使用二阶差分来维护。

虽然枚举段仍然是 O(n2) 的,但是注意到这个贡献只和段长有关,而段长的和是 n,所以不同的段长至多是 O(n) 种的,枚举出现过的两个段长统计即可。

时间复杂度 O(n)

D#

巨大困难题,dp of dp。

考虑一个数的 f(x) 如何计算,发现这个显然规约子集和,只能做类似背包的东西。我们设 fi,j 表示用了 i 位数当前的差是否可以为 j,转移时如果加入了一个 c 可以转移到 fi+1,j+cfi+1,|jc|。事实上第一维可以扔去,只保留 fi 表示差值为 i 的可行性。

因为单个数计算的复杂度是不可能再低下去了,我们就只能计数有多少个数的 dp 状态是合法的,那就只能是 dp of dp。看上去直接把 f 设在状态里状态数直接升天了,但是先别急,我们慢慢降。

首先一个观察是最后的答案一定不超过 9,因为考虑一个贪心:每次往和小的集合里扔数,这样能保证最后差不超过 9。而我们又注意到,如果某个时刻两个集合的差大于了 72,那么即使剩下位全都是 9 扔过去答案也不会小于 9,所以说我们的 f 其实只需要保留 f0f72 的状态就好了,这样我们可以直接用一个 int128 表示 f

现在的状态数是 273 左右,还是很爆炸。因为填的数最多只有 19 位,我们直接爆搜,搜出所有的合法状态,发现只有一万多种!

所以我们可以直接把这一万多种状态拉出来做 dp of dp 了。预处理 glim,len,S 表示限制差值不超过 lim,还剩下 len 位数需要填,当前的状态为 S 时还有多少种填法,转移是容易的。对于询问,显然要先差分掉,然后我们枚举 lcp 直接在 g 这个自动机上走就能统计答案。

跑得相当快,CF 上只跑了 234ms。

8.8

/shui/shui/shui/shui/shui/shui

8.9

巨大抽象模拟赛,我直接当场坠机了/cf/cf/cf。

打了高贵的 100+0+0+0!!!!!

A#

脑瘫题,开桶把次数拉出来双指针扫即可。

对桶做桶排可以线性。

B#

抽象题,一点不会啊啊啊啊啊啊。

考虑一个中心点和它的上下左右:

Copy
.1. 3#4 .2.

我们可以把填 L 理解成:在 12 中选一个填、在 34 中选一个填,是两个二选一的形式。

然后我们考虑在它们之间连边,通过给边定向的方式来描述选哪个(???????)。具体地,找到原来的图中的每个中心点,把它对应的 1,23,4 之间连边,相当于是求给整张图的边定向的方案数,使得每个点的入度至多为 1。这里是通过给边定向,边指向的点代表被选来描述的,所以入度代表的就是被几个中心点选中了。

特别地,给每个中心点自己连一个自环,上下左右有超过边界的就把连向对应点改成连向自己。

有了这个就比较好做了,我们找到图的每个连通块,然后进行讨论:

  • 如果连通块是一棵树,假设有 x 点,那么可以钦定任何点为根然后构造出一棵外向树,所以答案乘 x
  • 如果连通块是一棵基环树,环是自环那就限制了方案唯一,否则环上的点可以是顺时针或逆时针定向,方案乘 2
  • 对于剩下的情况,则代表边数大于点数,显然无法定向使得每个点入度不超过 1,报告无解。

做完了,可以做到 O(nm),我的实现是用的并查集。

为啥会想到通过给边定向来描述啊?这是啥我没见过的常见套路吗/ll/ll。

C#

说实话场上这题想到的要比 B 更多一点,感觉相对不那么抽象。

直接操作原串太复杂了,我们肯定要思考的是如何判断一个完整的串能不能删完,如果能做到快速判断这个可以直接写一个线性 dp 在 T 上分段转移求出答案(每次枚举一个能删空的段)。

为了方便,下文中令 L=a+b

判断一个串 S 能否删空的必要条件很好找,充分的不太好找,不妨先写出来:

  • |S|L 的倍数,因为每次删的串长是固定的 L
  • S 中恰好有 |S|aL0|S|bL1,因为每次删掉的 0,1 数量也是固定的。

我场上的思考就到这里结束了,因为没敢猜,事实上这两个条件还是充分的(为啥会不敢猜啊???),证明我直接贴下题解。

所以这个时候暴力做法就很显然了,像上面提到的,设 fi 表示 T 的前 i 位最多能操作几次,转移:

  • 先不管,直接继承,有 fi1fi
  • 拼上一个能删空的段,假设这个段的长度为 kL,有 fikL+kfi,同时限制 T(ikL,i]0 的数量不超过 |S|aL 个且 1 的数量不超过 |S|bL,因为只要不超过就可以把 ? 替换到合法。

直接做是 O(n2) 的,需要优化。

显然瓶颈在于第二种转移上,我们尝试形式化地描述出第二种转移。

我们前缀和一下,分别记 xiyi 表示前缀的 0/1 个数,假如要从 j 转移到 i,需要满足:

  • j<iijL 的倍数。
  • xixj|S|aL
  • yiyj|S|bL

容易发现每条限制 i,j 之间都是独立的,所以转移的限制实际上是个三维偏序,CDQ 分治优化即可。

对于模 L 同余的限制,分治的时候直接把每个余数拉出来分开做就好了,因为只需要处理左区间对右区间的转移。

时间复杂度 O(nlog2n)

posted @   KingPowers  阅读(50)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
CONTENTS