2022.2

2022.2

只记录一些我喜欢的题 还有一些模拟赛时没想到的 key observation

剩下的题只是因为我不会

2.8

T1

有时候不合法的决策一定不优于答案,这时候可以扩大决策集合。

这题就令 0j<ij 都转移到 i 就裸的斜率优化了。

T2

话说这个按编号二进制下每位是否为 1 分类是不是很常见的思路啊。

2.10

T1

给你 n 个数,其中有 k 个奇数,你可以花费 ci,j 的代价把 aiaj 同时减 1,问最小花费。

n50,k8

但怎么建图?

考虑只有偶数,对 i,j 的一次操作看成 i,j 之间的一条边,所有操作构成一个图,每个点的度数都是偶数,所以一定可以拆分成若干个环,我们给环上的边定向(顺时针还是逆时针无所谓),每个点的入度都等于出度,这样我们建费用流时就可以把每个点拆成入点和出点,源点向出点连流量 ai/2 的边,入点向汇点连 ai/2 的边,出点和入点之间连流量正无穷,费用 ci,j 的边。

加上奇数的话,所有操作构成的图就不能全部拆成环,还会多出一些首位是奇数点的链,注意到 k 非常小,于是可以 (kk/2) 枚举那些奇数点是入度比出度大 1(其余的就是出度比入度大 1),从源点连的或连向汇点的边流量就是 ai/2ai/2,这样就做完了。

T3

真的是太喜欢这个题了

第一次看到点分树这种用法

题意大概是给你一棵树,点 i 向树上距离 i 不超过 ri 的点连边,形成一个有向图,求缩点 DAG 中入度为零的点个数。

n3×105

暴力建图做 tarjan 就 Ω(n2) 了,寄,原因在于边数太多

如果有一种复杂度可以接受的 dfs 方式搜一遍所有点,那 dfs 序的逆序就是拓扑序(忽略一个强连通分量里的顺序),在按拓扑序搜一遍就得到零入度点的个数了。

点分树

我们记录下每个点的各级分治重心,和每个点作重心时他那层的所有点,并按到重心距离排序。

这部分空间复杂度是 O(nlogn),我们再对每层维护一个指针(类似当前弧优化),这样遍历每层的复杂度也保证了。

我们现在 dfs 到点 x,然后我们以此考虑 x 的各级分治重心,从指针指的位置继续往下 dfs,指针指的点到 x 的距离超过 rx 就 break 掉,继续考虑下一个分治重心。

然后我们就发现整个 dfs 的复杂度就是 O(nlogn),What a coincidance!

2.12

T1

区间DP,感觉不太难啊,为什么做不出来

T2

挺好一个题,可惜被一车人的 O(n2) 暴力吊起来艹,我 O(nnlogn) 却毫无悬念拿了 50 pts /fn

一个 key observation 就是答案的边一定在最小生成树上。

然后就只需对每个点维护其在 MST 上的孩子,具体地,我们要维护:

  • 该点的孩子的颜色集合
  • 每种颜色对应的边权的集合
  • 这些颜色对应的边权的最小值的集合
  • 所有点的各颜色对应的边权的最小值的集合的最小值的集合(其实就是全局的答案)

修改依次修改每个集合即可,总复杂度 O(nlogn)

总结:是一道非常好的 STL set 练习题

T3

给你序列 v,计数满足下列条件的长 n 的正整数序列 a

  1. aivi
  2. 序列中不存在 border

模数 998244353n106

题面简洁,感觉像经典题(?

先设计 DP,fi 考虑用总数减去有 bordor 的串个数,后者枚举最小 border 计算。

v 的前缀积为 ssi1si 的逆元,则有

fi=sij1i/2fjsijsj1

这个转移像个卷积,于是想到分治 NTT,因为转移一定有 jij,所以我们分治的时候,用左面的 fjsj1 和右面的 sij 卷,再转移到对应位置(可能再区间外)。

再减小常数,我们只需要计算出 [1,n/2]f,最后 O(n) 计算 fn 即可,还有,l+mid+1>n/2 的区间是不用做 NTT 的,因为会转移到范围外。

O(nlog2n)106,彳亍。

2.14

T1

题意好长...... 不写了。

好喜欢这个题,所以让我复述一下题解

先考虑没有问号的情况,我们维护一个栈,两个两个操作,每次我们可以 :

  1. 将两位依次压入栈中
  2. 将第一位与栈中全部元素合并后,再将第二位压入栈中

栈中的情况可以用一个关于下一个压入元素的函数描述,即 F[a,b](x) 表示当 x=0 时返回 ax=1 时返回 b。根据上面两种情况,我们很容易得到当前栈加入两个数后的新栈的情况,这样 fi,j0,j1 表示到第 i 位,栈的状态为 F[j0,j1](x) 是否可行,状态数为 4n

加上问号,我们可以考虑 DP 套 DP,把 4fi0 还是 1 状压起来,复杂度是 162n

T2

看了两个小时硬是没看出来 SG 函数是啥,我自裁

每个棋子是独立的,总的 SG 函数就是每个棋子的 SG 函数异或和,这很难想到吗?

单个棋子的 SG 函数就是它到子树内距它最远的点的距离(这个倒很容易猜到)。

然后就变成数据结构题了,树剖维护,还有就是看到这种最远距离应该能想到直径,所以把直径拎出来做要容易些,不过依然有不少细节要分类讨论,码了 5.3K,十分舒适。

T3

一眼看好裸的最大权闭合子图

复习了一下建图方式

  • 对所有正权点 i,连边 si,容量为点权
  • 对所有负权点 i,连边 it,容量为点权绝对值
  • 原图中所有边也都连出来,容量为正无穷

则有,最大权闭合子图的权值 = 正点权之和  maxflow

这个题有一个问题就是选出的子图不能为 ,所以我们要依次删掉每个点强制选它,但每次建图跑网络流复杂度不能接受,不过因为每次我们都只改了一条边的容量,所以不用重新建图,只需再残量网络上退流,再重新增广即可。

[NOI2012] 美食节 这个题好像也是,有空看看。

2.16

T1

一个小结论,线性基 B 能表示 2i 当且仅当把 B 消成对角基之后的第 i 行只有第 i 列为 1

然后这个题我只会 O(n3lognω)O(n3ω) 的做法没听懂/dk/dk/dk

T2

参考 IOI2022国家集训队论文 彭博《图染色问题初探》

众所周知的四色定理指出,任意一个平面图都可以四染色,然而构造方案却不太容易,不过对平面图的五染色却存在很简单的构造方法。

先证引理

Lemma:任意一个平面图中一定存在度数小于等于 5 的点

记平面图的点数为 V,边数为 E,联通块数为 C,把平面划分成的区域个数为 F,由平面图的欧拉定理有 E=V+FC1V+F2。因为每个平面区域至少由三条边围成,每条边被两个平面区域共享,所以有 F23E,两个不等式相加得到 E3V6。所有点的度数之和 2E6V2<6V,由抽屉原理,必然存在一个点的度数小于等于 5

接下来给出五染色构造方案

对于平面图 G,找出一个度数小于等于 5 的点 x,删去 x 及与其相连的边,得到平面图 G,我们归纳假设已经构造了 G 的五染色方案,现在要给 x 染色。

如果与 x 相连的点小于 5 个或者有相同的颜色,那么 x 可以直接染色,否则,我们记与 x 相连的点为 ai (i=1,2,3,4,5)a1a5 顺时针排列,不妨设 ai 的颜色为 i,我们从 a1 出发找到所有与其相邻颜色为 3 的点,再从这些点出发找到与它们相邻的所有颜色为 1 的点,依此类推,得到一颗颜色交错的树 T,如果 a3T,那我们可以把 T 中所有点由颜色 1 变成 33 变成 1,然后把 x 染色 1。如果 a3T,我们再从 a2 出发对颜色 24 做相同操作,记得到的交错树为 T,由平面图性质,一定有 a4T(因为 a1a3 的路径和 a2a4 的路径一定相交),将颜色 24 交换后,我们就可以把 x 染色为 2

这样我们就有了平面图五染色的 O(n2) 构造算法。

回到这道题,因为所给图的特殊性质,一定存在度数小于等于 4 的点,我们可以用类似方法构造四染色。

T3

赛时已经想到正解了可惜抱零了,赛后重构一遍代码,码了 5.6K 终于过了/tuu

因为是自己想的,所以不写题解了

2.18

T1 是垃圾题,T2T3 都没听懂,完了。

2.19

T1

我写的题解做法,不过好像写的比别人都长(?)

题意:

给你一个长度为 n 的序列,初始每个点的颜色都不同,每次操作合并两个颜色,求最短的区间 [l,r] 的长度,使 [l,r] 中包含所有颜色。

n105

这个题也是,真是太喜欢了

首先肯定想到启发式合并,这样就转化为 O(nlogn) 个单点修改。

然后,看到颜色种类,就想到了记 prei 表示 i 前边第一个颜色和 i 相同的位置。

但这个并不是固定区间的询问,怎么处理,我们非常巧妙地记 fi=max{j |prej<i},这个 fi 就是 i 做左端点时使区间合法的最近的右端点。现在我们看看如何维护 f

我们每次会修改一个点的 pre(一定是使 pre 值变大了),这会使一些点的 f 值变小。假设我们修改了 prei,容易发现受到影响的 f 一定是满足 fj=i 的,而且这些 f 一定是连续的一段(因为 f 是单调不下降的),修改之后这一段 f 会被分裂成若干段。我们用线段树维护 f,我们在线段树上二分找出满足 fj=i 的区间,然后暴力地一段一段修改即可(区间赋值)。这样的复杂度是正确的,考虑最多会产生 n 个段,而每次操作最多会造成一次两个段的合并,所以这样的区间修改总共只有 O(nlogn) 次。

还有一个问题,如何求出新的 f,也就是说如何求最大的 j 使 prej<i,考虑再开一个线段树维护 pre 及其后缀最小值,这样就可以线段树上二分求出 f

最后还有一个小问题,并非所有的 fii+1 都能作为答案,设 p 是最靠后的满足 [p,n] 包含所有颜色的位置,那么答案应该是 i[1,p]fii+1 的最小值,p 随着不断修改操作是单调的,直接一个指针维护就好了。

这样就以 O(nlog2n) 的复杂度做完了!

T2

n 个选手编号 0n1,初始时,有一个数字 x=0,选手 0n1 依次选择是否进行操作,选手 i 进行操作可以将 x 变为 (x+ai)modn。最终的 x 就是胜者的编号。一个选手进行操作当且仅当他能获胜,且不进行操作无法获胜

序列 a 最初给定,之后 q 次单点修改,每次你要求出胜者编号。

n3×105

pi=(iai)modn,因为进行操作的人只会令 x 变成他自己,所以 pii 是无用的,从 ipi (pi<i) 连边,形成一个内向树森林。

fi=0/1 表示若当前 x=ii 能不能赢,则有 fi=1 当且仅当 json(i),fj=0,这样树形 DP,最后 0 号节点编号最小的等于 1 的儿子就是胜者,若没有,答案就是 0

带上修改操作,我们就在 LCT 上动态 DP 就可以了,重儿子的转移可以写成 g(x)=kx+b 的形式(k,b 适当地取 0,1,1)。

23 号也有一个 LCT 做的动态 DP,其实写起来感觉差不多。

T3

给你 AC 自动机的 trie 树和 fail 树(根不确定),请你构造出一个符合条件的 AC 自动机。

n3×105

题解垃圾 O(nlogn) 做法也没看懂,实际上做到 O(n) 还是比较简单的说。

先假定确定了根怎么做(之后再说怎们找根)

考虑 fail 树,根节点每个子树显然是一个相同的字符,所以直接给每个点标好字符,(一些显然不合法的情况要判掉,比如 fail 边从 trie 上深度浅的点指向深的点)。

然后要检查 x 的 fail 边指向的点是否是从 fax 开始跳 fail 边第一个遇到的有和 x 相同字符孩子的点。我们在 fail 树上 dfs,在过程中维护 mpc 表示上一个遇到的有 c 孩子的点,这个很好在 dfs 以及回溯过程中维护。还有一些情况比如 trie 树上有一个节点两个孩子被赋上了相同字符也要判掉。

现在我们考虑怎么找根,如果两点 u,v 之间既有 trie 边又有 fail 边,那就说明当前点对应的字符串有长度为 len1 的 border,那它的循环节就是 1,也就是说,所有这样的公共边构成从边出发的一条条链(一个爪子形),度数大于 2 的点就是根。

如果所有公共边构成的是一条链,我们考虑链上一个点 x 在 trie 树上的邻居,它代表形如 aaa...ab 这样的串,从它出发跳 fail 边,回到链上,假设跳到了链上的点 y,那么 y 代表的要么是 b,要么是空串,所以根节点一定是 yy 在链上的邻居,逐个检查这三个点即可。

这样就做完了!

2.21

今天题相对来说简单多了啊

T1

题意很容易转化成求 LIS 以及哪些位置在所有可能的 LIS 中。从两边分别 DP 并统计方案数,对每个位置检查其两侧的方案数乘积是否等于总方案数(可能会很大,记得取模)

想到 DAG 必经边的经典做法,这个题就很容易想到了。

T2

题意

一棵 n 个节点的树,每个点可以填一个 [li,ri] 中的整数,需满足相邻两个节点上的数互质。对每个点求其在所有合法方案中上面的数之和。

n50,liri50000,对 109+7 取模。

直接 DP,fx,i 表示点 xi 在其子树内的方案数,转移就是

fx,i=yson(x)j=1m[ij]fy,j

(这里忽略了 li,ri 的限制,m 为值域,具体实现时把不在 [li,ri] 范围内的 fi 设为 0 即可)

直接莫反

j=1m[ij]fy,j=j=1mfy,jk|i,k|jμ(k)=k|iμ(k)k|j,jmfy,j

后面这一大坨都可以 O(mlogm) 处理出来,这样整个 DP 以此就是 O(nmlogm) 的。

对每个点求答案,换根 DP 就可以。

还有,关于换根的写法,我们可以记录每个点孩子前缀和后缀的 DP 值,这样换根的时候就避免了减去贡献,有的时候会简单很多。

T3

转化后的题意大概是给一个括号串,区间询问,求区间内最长的合法括号序列。

n105,m4×106

把左括号看作 1,右括号看作 +1,前缀和之后就是一个若干山峰状的序列,就是求区间内注水,形成的最长连续水面长度(非常形象)

首先能想到 O(nm) 的回滚莫队。

然后还有一个做法是倍增,记 ri 表示 i 右面第一个比它大的位置,li 同理,答案一定是一个区间 [i,ri1][li+1,i]。我们倍增地跳 lr,就可以在线 O(logn) 单次询问了。

稍微想想好像也能做到 O(1) 单次询问。总之都可以通过。

2.23

T1

容易得到 DP

fx=yson(x)max{fy,1}[yson(x)fy=0]

DP 选的根节点必须度数大于等于 3,否则答案就是 1

加上 Link,cut 操作,考虑在 LCT 上维护动态 DP,一个节点 x 从重儿子的转移可以写成分段函数

存在轻儿子 DP 值为 0

gx(val)={s+1val=0val+sval>0

不存在

gx(val)={sval=0val+sval>0

其中 s 是所有轻儿子的 DP 结果。

这个分段函数是容易复合的,所以就可以做了(动态 DP 能维护的奇怪东西增加了!)

几个实现细节:

  • 考虑有换根操作(链翻转),所以维护一个从上到下的复合和一个从下到上的复合,reverse 的时候直接 swap 两者即可
  • 为了得到一个实链顶端的 DP 值,我们发现给整个链上的函数代入 0 是不对的,所以我给维护的函数加了一段,代入 1 得到的是链顶的 DP 值
  • x link 到 y 上的时候要先 access 一下 y,否则上面虚边的信息都错了(调了好久)

T2

原题:https://blog.csdn.net/weixin_45313881/article/details/104032690

所以就不写题解了,这道题还是很好的。

能不能用这道题解法求边三联通分量?

2.27 Update:好的,A 掉了洛谷模板题,看来是能的 https://www.cnblogs.com/sapphire162/p/15941274.html

T3

寄吧题,毫无难度只需大力分类讨论去构造。(但我也没切,好像没资格这么说)

posted @   iMya_nlgau  阅读(92)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
点击右上角即可分享
微信分享提示