2024.3 记录

3.5

vp 了一场 edu,过了四题,但是 D 题有 *2100,自我感觉还行。

这里写一下后三题的题解。

CF1913D Array Collapse#

数字互不相同,先上个单调栈求出每个点的支配区间。

考虑 dp,fi 表示只考虑 [1,i] 时的方案数,找到最靠左的 j 满足 [j,i] 间不存在小于 pi 的数,那么 [j,i1] 这些位置的 dp 值都能转移到 fi

除此之外,以 j1 结尾的最长上升子序列也都能转移到 fi,因为这些位置与 i 之间的数一定可以被删去。

随便优化下转移就能做到 O(n)

提交记录

CF1913E Matrix Problem#

考虑一个显然但错误的建模方式:每行每列建一个点,S 向每行连容量 ai 费用 0 的边,每列向 T 连容量 bi 费用 0 的边,i 行向 j 列连容量 1 费用为矩阵 ij 列的数取反的边。

至于为什么错误,因为我们矩阵中原来的 1 对应了一条费用为 0 的边,为了使费用最小我们肯定会优先流 1 而不流 0,如果某行某列有多于限制数量的 1 也不会改回 0,也就是说求出来的相当于是“至少”而不是“恰好”的答案。

考虑先将矩阵全都变成 0,然后原来费用为 0 的边改成 1(相当于把对 1 的取反撤销),这样就流对了。

提交记录

CF1913F Palindromic Problem#

考虑求出 fi,c 表示将 si 的字符改成 c 之后回文子串数量的变化量,有了这个输出答案就是一些无聊的分讨。

先考虑什么时候改字符会增加,假设有一个回文中心 i 和回文半径 r(这里是子串长为奇数的情况,偶数是类似的),那么只有使 sirsi+r 字符相同时才会有新的贡献,注意贡献不止是 1,应该再加上后缀 [i+r+1,n] 与翻转后的前缀 [1,ir1]lcp

然后再考虑什么时候会减少,显然更改一个字符会使所有原先经过它且不以它为中心的回文子串消失,只需要求出每个位置被多少回文子串经过即可,这个枚举回文中心后贡献是一个等差数列的形式,可以二阶差分维护。

然后就做完了,这里求 lcp 用的是后缀数组,时间复杂度 O(nlogn+n|Σ|)

提交记录

晚上学了下 Hall 定理。

CF338E Optimize!#

b 的顺序显然不影响匹配,由于有不等式的限制不难想到先将 b 排序。

单独看 a 的一段长度为 m 的子区间,设 f(i) 表示 bi 能匹配的集合,根据 Hall 定理,存在完美匹配需要满足对于任意的 km,任取 1i1<i2<<ikm,都有 |f(i1)f(i2)f(ik)|k

因为 b 排序过,所以任意的 i<j 均有 f(i)f(j),显然上式成立等价于 |f(k)|k

线段树维护 |f(i)|,初始令第 i 个位置为 i,每加入一个 ai 相当于做一个区间加,满足条件相当于全局最小值非负,这都是好维护的。

时间复杂度 O(nlogn)

提交记录

3.6

CF1930F Maximize the Difference#

见我的洛谷专栏

ABC235G Gardens#

直接容斥,枚举至多 k 个盒子有球。

k=0n(1)nk(nk)(i=0A(ki))(i=0B(ki))(i=0C(ki))

内层的组合数求和是典中典,可以直接递推,然后就 O(n) 做完了。

提交记录

CF1863F Divide, XOR, and Conquer#

牛逼的思路。

看见 n104,我们直接一反常规,考虑区间 dp:记 dpl,r 表示区间 [l,r] 是否能被保留。

然后有个显然的 O(n3) 做法,这里不多赘述。

suml,r 表示区间 [l,r] 的异或值,[l,r] 能被保留当且仅当存在一个更大的可保留区间 [L,R](需要满足 L=lR=r),满足 suml,rsumL,Rsuml,r,这步根据题面显然成立。

一个小性质:xyx 当且仅当 xy 的最高位上是 1

Li 表示所有被保留的左端点为 i 的区间,它们的异或和的 higbit 取值集合(用个 long long 存),同理定义 Ri 为所有被保留的右端点为 i 的区间,[l,r] 能被保留就相当于是 suml,rLiRi 按位与的结果不为 0

于是做到了 O(1) 转移,时间复杂度 O(n2)

当然上面的讨论都是基于区间异或和大于 0,等于 0 和谁拼一块都行,注意特判。

提交记录

3.7

CF1930E 2..3...4.... Wonderful! Wonderful!#

注意到删除的数字数量 x 一定为 2k 的倍数,因此枚举 k,x 是调和级数的复杂度。

记保留为 0,删除为 1,相当于是对一个 01 序列计数。

一个结论是,合法当且仅当至少存在一个 0 两边 1 的个数都至少为 k,归纳易证。

还是不太好数,考虑容斥,用总数 (nx) 减去不存在合法 0 的情况。

初始一个长为 x 的全 1 串,插入 nx0,那么这些 0 只能插在两边 k11 旁,否则一定就有合法的 0,一共有 2k 个合法的位置,直接隔板即可。

时间复杂度 O(nlogn)

提交记录

P5590 赛车游戏#

这么你哦。

边权不好定,考虑限制整个路径长度。

disi 表示 1i 的最短路,发现只要每条边 (u,v) 都满足 1disvdisu9 就能构造出合法答案,否则一定存在一条长不相同的路径(注意当边不在任何一条 1n 的路径上时不应被考虑)。

然后对这个限制跑差分约束即可,时间复杂度 O(nm)

提交记录

ABC232G Modulo Shortest Path#

见我的洛谷专栏

P3530 [POI2012] FES-Festival#

先建立差分约束图,判断是否有解。

对差分约束图按强连通分量缩点,由于不同 SCC 之间的距离可以无限拉大,不同 SCC 之间答案独立。

对于每个 SCC,找到其内部的点对 u,v 满足 disu,v 最大(disi,j 表示 ij 的最短路),那么这个 SCC 答案就是 disu,v+1,将所有 SCC 答案加起来即可。

比较感性的理解就是因为边权只有 1,0,1 三种,disu,v 之间的数一定能取遍。

时间复杂度 O(n3),因为要跑 Floyd。

提交记录

3.8

CF960H Santa's Gift#

见我的洛谷专栏

3.9

CF1879F Last Man Standing#

显然,x>maxai 是无意义的,且第 i 位玩家坚持的回合数一定为 hiaix

考虑枚举 x,对于每个 x 我们只需要求出来坚持回合数最大和次大的玩家即可。

再用一个调和级数的复杂度固定 aix,那么此时 ai 取值范围就是一个区间,在一定的值域范围内回合数就只和 hi 相关了,只需要维护出 hi 的最大值和次大值即可。

这题卡常,必须严格 O(nlogn),考虑 ST 表维护 hi 的最大值和次大值即可。

注意 ST 表要维护下标,因为直接合并最大值和次大值是错的。

提交记录

3.10

CF1902F Trees and XOR Queries Again#

有一个经典的做法,考虑线性基的合并是可重的,将询问 (x,y) 拆成 xlcalcay 两段,每段像 ST 表那样倍增拆成两个可重区间合并即可,由于线性基合并是 O(log2V) 的,这个做法是三个 log,能不能过不好说。

更优的做法是考虑点分治,维护出连通块内每个点到分治中心上的线性基即可,每次回答跨过当前分治中心且完全位于当前连通块内的询问即可,复杂度 O(nlognlogV)

提交记录

CF1059E Split the Tree#

见我的洛谷专栏

3.11

CF1679F Formalism for Formalism#

钦定每个等价类在字典序最小的数被统计,这个数满足一个性质:不能通过交换使得字典序变小。

进一步刻画这个条件,假设当前在填第 i 个数,设存在一个极长后缀 [j,i1] 满足这段内的数都能和 i 交换,充要条件就是这些数都不大于 i

设计 dp 统计:设 fi,S 表示填了 i 个数,S 内的数不能填的方案数。提前预处理 toS,i 表示不能填 S 内的数时填 i 后转移到的集合,即可轻松转移。

时间复杂度 O(nd2d),其中 d=10

提交记录

P8089 『JROI-5』Color#

考虑直接在树上 dp,fu 表示 u 子树内的方案数,显然 fu=(fls+1)(frs+1)

经典结论:完全二叉树可以拆成 O(logn) 棵满二叉树,显然每个点的左右子树至少有一棵是满二叉树。

对于满二叉树,预处理 fi 表示深度为 i 的满二叉树的答案,然后把原树拆成若干满二叉树合并即可。

提交记录

CF1082G Petya and Graph#

考虑最小割,先把答案加上所有的边权,建模流出最小损失。

S 表示选,T 表示不选,最小割模型大致如下:

  • 对于任意一个点 x,如果选 x 则产生 ax 贡献,连边 xT,容量 ai 即可。
  • 对于任意一条边 (u,v,w),如果 u,v 不同时选则产生 w 的贡献,建一个虚点 p,连边 Sp,pu,pv,容量均为 ai

然后就做完了。

提交记录

3.12

ARC159D LIS 2#

若只题/bobo。

一个非常显然的观察就是,当一个上升子序列以第 i 个区间结尾时,第 i 个区间一定会扩展到 ri

直接 dp,设 fi 表示以第 i 段区间结尾且扩展到 ri 的 LIS 的长度,暴力转移显然:

fi=maxj<i{fj+rili+1,rj<lifj+rirj,lirjri

两种情况分开维护,发现都是二维偏序,直接线段树优化即可。

时间复杂度 O(nlogn)

提交记录

ARC171D Rolling Hash#

为了方便,不妨将 Ai 全部模 p 考虑,也就是假设 0Ai<p

sufi 表示后缀 [i,n] 的哈希值,注意这个可能和你理解的后缀哈希值不太一样:

sufi=j=inAiBni

sufi 是可以在 [0,p1] 任意取值的,且 sufi 的每种取值都可以唯一对应一个 A 序列。

则哈希函数可以重写如下:

hash(l,r)=i=lr(AiBri)=Brni=lrAiBni=Brn(suflsufr+1)

由于 B<pBk 恒不为模数 p 的倍数,故 hash(l,r)0 等价于 suflsufr+1

不难发现,当 p>n 时一定存在解,先判掉。

不妨对现在的问题进行一个具体的建模,建立 n+1 个点,限制区间 [l,r] 就连边 lr+1,现在的问题就转化成了:对图上的点进行染色,使得不存在一条边连接的两个点颜色相同,求最大颜色数是否不小于 p

这是个经典的无多项式解法问题,考虑状压,设 f(S) 表示染完集合 S 内的点的最大颜色数,转移考虑枚举 TS,如果 T 是一个独立集那么 T 就可以染成相同颜色,就有转移 f(S)f(ST)+1

判断独立集可以暴力预处理,总复杂度 O(3n)

提交记录

ARC162D Smallest Vertices#

有点魔怔的题,需要点 Prufer 序列的前置知识,这里是我的小总结

需要注意的是因为 di 表示的是出度,因此对于 2ini 的度数实际上是 di+1

对于每种树求有多少个好的顶点是非常困难的,我们不妨换个角度,钦定每个点为好顶点,然后求出此时有多少棵满足条件的树累加即可。

首先是一种特殊情况:对于 1 号点和叶子结点,显然无论在哪种树中它们都符合条件,此时直接套公式把树的总数累加进答案即可。

对于其它结点,假设我们现在要求 i 号点是好的,那么 i 子树内的点编号一定在 [i+1,n] 之间,同时如果 i 的子树内有 k 个点那么还要求这些点的出度之和恰好为 k1。容易设计一个 dp 统计出选点的方案数:令 fi,j,k 表示在 [i,n] 中选了 j 个结点,出度之和为 k 的方案数。

然后再套用公式分别计算出子树内和子树外的连边方案数即可,算子树外的方案数时将 i 号点看作一个叶子即可。

时间复杂度 O(n3),瓶颈在背包上。

提交记录

P7142 [THUPC2021 初赛] 密集子图#

卡常屑题,不知道为啥我代码就是过不去。

边权为 1 且与最短路相关考虑分层,设 fi,s1,s2 表示当前已经考虑了 i 层,最短路不超过 i 的点集为 s1,最短路恰好为 i 的点集为 s2 的概率。转移考虑枚举下一层的点集 s3,那么就要求 s1s2 的点不能向 s3 内的点连边,s3 内的每个点 s2 至少都向其有一条连边。

预处理 gs1,s2 表示 s1s2 之间没有连边的概率,hs1,s2 表示 s2 内的每个点都至少有从 s1 连来的边的概率,就能直接转移了,容易做到 O(n4n)

我死活卡不过去了,代码不放了。

3.13

CF461B Appleman and Tree#

一眼题,设 fu,0/1 表示只考虑 u 子树内,u 的连通块内有 0/1 个黑点时的断边方案数。

  • fu,0fu,0×fv,0+fu,0×fv,1
  • fu,1fu,1×fv,0+fu,1×fv,1+fu,0×fv,1

没了,时间复杂度 O(n)

提交记录

CF547E Mike and Friends#

先对所有串建 AC 自动机。

询问 skslsr 的出现次数,显然可以差分成 s1sr 的出现次数减去 s1sl1 的出现次数,把询问挂到对应的串上,然后离线考虑。

对于每个 si 都从根开始在 trie 上走一遍,并把走过的点点权 +1,当前 i 个串都走完时,询问 sks1si 的出现次数就相当于询问此时 sk 的终止结点在 fail 树上的子树和,树状数组维护即可。

时间复杂度 O((n+q)logn)

提交记录

P8867 [NOIP2022] 建造军营#

重新写了一个更加通用且更 educational 的做法。

显然被攻击的边只会是割边,因此将原图边双缩点,在树上考虑问题。

现在问题转化为了,在树上选一些点,要求选的点构成的虚树上的边必选,其它边可选可不选的方案数。

fu,0/1/2 表示 u 子树内没选点/选点但 lca 不为 u/选点且 lcau 的方案数,转移平凡,在所有的 fu,2 统计答案即可做到不重不漏。

提交记录

3.14

CF1515E Phoenix and Computers#

观察到在两边插入是好处理的,但是中间比较难,因此考虑连续段 dp。

fi,j 表示已经打开了 i 个电脑,形成了 j 个连续段的方案数,转移就是分那么几种情况:

  • 插入到某个连续段的两端,可以紧贴着插或者和端点空一个。
  • 新建一个连续段。
  • 合并两个连续段,注意这时新增的电脑数可能为 23

时间复杂度 O(n2),转移系数不具体写了。

题目链接

P5999 [CEOI2016] kangaroo#

题目可以转化为,有多少种排列满足首尾为 s,t 且每个数要么比两边大,要么比两边小。

排列插入的问题同样可以考虑维护连续段的 dp,设 fi,j 表示插入了 [1,i] 形成了 j 个连续段的方案数,特判 is 或者 t 的情况,对于其它情况的转移:

  • 新开一段,不难发现一定合法,fi,j(j[i>s][i>t])×fi1,j1
  • 扩展某一段,不难发现一定非法。
  • 合并两个段,fi,jj×fi1,j+1

时间复杂度 O(n2)

提交记录

P7967 [COCI2021-2022#2] Magneti#

建议直接看这里一份总结:浅谈一类状态转移依赖邻项的排列计数问题:连续段 dp(线头 dp) - ChroneZ - 博客园 (cnblogs.com)

3.15

P5574 [CmdOI2019] 任务分配问题#

有一个显然的 dp,设 fi,j 表示前 i 个数分给了 j 个 CPU 的最小代价。

fi,j=minkifk1,j1+calc(k,i)

其中 calc(l,r) 表示 [l,r] 的顺序对数,暴力转移复杂度 O(n2k)

但是这种形式想都不用想肯定带决策单调性,直接树状数组维护顺序对分治即可。

时间复杂度 O(nklog2n)

提交记录

3.16

去学了下 FWT 板子,虽然是 useless 的东西。

3.18

CF1051F The Shortest Statement#

一定要注意到图是稀疏图。

先任取一棵原图的生成树,如果最短路仅经过树边,可以直接求 LCA 回答。

将所有的非树边的端点拉出来,分别以其为源点跑一遍 dijkstra,用于更新经过了树边的答案。

显然最多跑 40 次左右的 dijkstra。

时间复杂度 O((mn)mlogn)

提交记录

3.19

CF1340C Nastya and Unexpected Guest#

发现我们并不关心安全岛以外的点,因此考虑在安全岛之间 dp,设 fi,j 表示当前在第 i 个安全岛,距离上次绿灯亮起已经过了 j 秒所经过的最小循环次数。

转移考虑当前时间加上路程是否刚好红灯,来决定是否要等到下一个循环。

当然这个转移关系显然是带环的,不过转移边权只有 0101BFS 即可。

状态定义为最小循环次数而不是时间的作用就在这里体现了,否则只能跑 dijkstra。

时间复杂度 O(mg)

提交记录

然后今天晚上去学了生成函数和多项式板子……天哪我到底在干嘛……

3.20

CF1715E Long Way Home#

因为 k20,所以这 k 次飞机票分开考虑,而且这个平方给人的感觉就很斜率优化。

我们令 dis 表示上一轮的最短路,本轮更新完的最短路为 dis,先考虑这次飞机票怎么飞:

disu=minvdisv+(uv)2

'简单拆一下:

disu=(2vu+disv+v2)+u2

显然是斜率优化的形式,懒得维护凸包了,我这里直接上了李超树,我用括号括起来的部分就是用李超树能维护的,相当于求若干个一次函数在 u 处的最值。

注意到飞完之后我们还会在地面上再走几条原图的边,把当前 dis 扔进小根堆再跑一遍 dijkstra 即可。

时间复杂度 O(kmlogn)

提交记录

posted @   KingPowers  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示
CONTENTS