DS 25.01

题单

P5070 [Ynoi2015] 即便看不到未来

啊,哦,啊,哦,嗯。

考虑离线扫描线,设 \(lst_i\)\(i\) 上一次出现的下标,显然 \(x\) 只会对 \(lst_{a_x}\) 以后的 \(l\) 有贡献。

题目只要求求出长度 \(\le 10\) 的连续段段数,也就是说,加入 \(x\) 只会对 \([a_x-10,a_x+10]\) 这些数字造成影响。

把这些数字按 \(lst_x\) 升序排序,从右往左处理,加入 \(x\) 会产生三种情况,左边新添一个数,右边新添一个数,两个连续段合并,开 \(20\) 个树状数组维护就好。

时间 \(O(nk\log n)\)

*P11488 「Cfz Round 5」Zhòng shù

这种题是可以放出来的吗,感觉质量好低。

考虑维护一个支持区间加全局 \(\max\) 的线段树,操作一方便维护,操作二每次只会产生 \(O(1)\) 个新链条,单独维护就好。

其他都是实现的问题。

时间 \(O(n \log n)\)

P5138 fibonacci

\(f_i\) 为斐波那契数列第 \(i\) 项。

\(f_{n+m}=f_nf_{m+1}+f_nf_{m-1}\)

一次修改 \((x,k)\)\(u \in \text{sub}(x)\) 的影响是,\(s_u:=s_u+f_{d(x,u)+k}\)

拆开得到 \(d(x,u) = d_u - d_x\)\(f_{d_u-d_x+k}=f_{d_u+1}f_{k-d_x}+f_{d_u}f_{k-d_x-1}\)

维护 \(f_{d_u},f_{d_u+1}\) 的系数,然后就做完了。

时间 \(O(n \log^2 n)\)

*Tree MST

第一眼菠萝,但是感觉自己不是很熟练,换想法。

发现 \(\text{dis}(u,v)\) 在点分治下面可以拆成 \(d_u+d_v\),直接点分治,每次所有点连 \(d_x+w_x\) 最小的点,同一子树内的点会更劣,不用考虑,最后再拉出来跑 kruskal。

这个做法的正确性是基于正权边的,带负权同一子树会算重,怎么办,一个好的办法是点分转边分。

时间 \(O(n \log^2 n)\)

*P7710 [Ynoi2077] stdmxeypz

出的很巧妙的题目,但是做起来比较直白。

首先把子树拍成序列,因为感觉操作和树结构没那么强的依耐性。

一操作看到直接根号分治,小的容易想到分块打标记,大的发现也可以分块维护差分数组。

时间 \(O(n \sqrt n)\),乱调块长都能过。

P5069 [Ynoi2015] 纵使日薄西山

感觉大脑被僵尸吃掉了。

题目等价于求一个极大值序列,两两的距离大于等于一,求这个序列的和。

这个序列明显是唯一的,考虑用线段树维护,讨论 \(s_{00/01/10/11}\) 代表 是/否 钦定 左/右 节点不选,另外需要维护左右端点是否被选的辅助信息。

时间 \(O(n \log n)\)

P5063 [Ynoi2014] 置身天上之森

首先注意到肯定不弱于根号,直接往根号方向思考。

  • 结论 1:线段树只有 \(O(\log n)\) 种节点长度。
  • 结论 2:线段树一层只有 \(O(1)\) 种节点长度。

然后每种长度开个分块维护一下,套用一下由乃打扑克,时间 \(O(m \sqrt{n \log n})\)

*P11527 [THUPC2025 初赛] waht 先生的法阵

等等,好像是上个月做的,算了,还是放进来吧。

场上过了。

看起来不太会 \(\log\),直接考虑根号,分块维护每个点跳出块需要几次,以及跳到哪个点,这个是简单的。

\(\gcd\) 最多变化 \(w\) 次,直接的思路是直接找到区间 \(\gcd(a_i,x) \ne 1\) 的块暴力修改,但是发现这样是 \(O(nw \sqrt{n \log n})\)\(w\) 是质因数个数。反正赛时第一遍写了这么个唐氏做法,没卡过去。

有点唐氏的是,第一遍没看到修改的值域 \(c_i \le 2.5 \times 10^5\),贴了个 \(\text{rho}\) 上去。

考虑优化,优化是简单的,参考 P5610 [Ynoi2013] 大学,每个质因数开一个并查集维护,每次修改直接暴力修改。

默认 \(n,q\) 同阶,总复杂度 \(O(wnB + \dfrac{n^2}{B} + n \log^2 V)\),视 \(w = \log V\),理论 \(O(n\sqrt{n\log V} + n \log^2 V)\)\(B\)\(80\) 左右跑得飞快,直接拿下最优解。

P11160 【MX-X6-T6】機械生命体

考虑 Trie。

首先,全局 \(+1\) 是经典套路,从低往高建 01Trie,每次修改将右链上所有点的左右儿子交换。

思考如何扩展到 \(+x\),发现 \(+x\) 会下放给左右儿子各加上 \(\left \lfloor \dfrac{x}{2} \right \rfloor\),特殊地,如果 \(x\) 为奇数,先对 \(x\) 子树做一次全局加一再下放。

看似是 \(O(n \log^2 n)\) 的,但是我们注意到全局加一并不需要直接暴力下传,给右儿子打标记,交换左右儿子即可。

考虑如何子树加,因为无法维护子树根到全树根的链上信息,我们要把那棵子树分裂出来,打上懒标记再合并回去,这个合并是线段树合并类的合并。

总复杂度 \(O(n \log V)\)

P11197 [COTS 2021] 赛狗游戏 Tiket

学到一个新的小 trick。

原题目等价于求三个排列的三维偏序。

我们设三个排列为 \(a,b,c\),长度均为 \(n\)

\(S_1= \{(i,j)|a_i < a_j\}, S_2 = \{(i,j)|b_i<b_j\},S_3 = \{(i,j)|c_i<c_j\}\)

答案集合为 \(S\),答案则为 \(|S_1 \cap S_2 \cap S_3|\),容斥得到 \(|S| = \dfrac{|S_1 \cap S_2| + |S_1 \cap S_3| + |S_2 \cap S_3| - |S_1 \cup S_2 \cup S_3|}{2}\)

接着,我们发现,\(|S_1 \cup S_2 \cup S_3| = \begin{pmatrix} n\\ 2 \end{pmatrix}\)

为什么?因为对于每一对 \((i,j)\),发现 \((i,j)\)\((j,i)\) 有且只有一对满足二维偏序。

这样三维偏序就被转化为三遍二维偏序,时间 \(O(n \log n)\),空间线性。

P5439 【XR-2】永恒

没做起,但是感觉套路。

我们记一对数对 \((x,y)\) 的贡献为 \(sum_{x,y}\),答案是 \(\sum\limits_{(x,y),x<y}\text{lcp}(S_x,S_y)sum_{x,y}\)

LCP 的长度就是 Trie 树上 LCA 的深度值,LCA 的深度反射出来将 \(u\) 到根的路径加一,然后查询 \(v\) 到根的和。

分类讨论 \(x,y\) 的祖先关系。

  1. 如果 \(x\)\(y\) 的祖先,那么 \(sum_{x,y}=siz_y(n-siz_x)\)
  2. 如果 \(x,y\) 无互相的祖先关系,那么 \(sum_{x,y}=siz_x siz_y\)

然后直接做就好了,时间 \(O(n \log n)\),实现了 \(O(n \log^2 n)\),空间线性。

*P4075 [SDOI2016] 模式字符串

简单题目,统计树上点对,考虑一个静态链分治。

选用点分治,然后发现很好计数,拿个哈希判一下匹配就好。

时间 \(O(n \log n)\),空间线性。

[ARC190E] Gaps of 1 or 2

接下来选自我的题解:

相当精巧的题目,反正我肯定做不起,写篇学习笔记。

首先我们考虑把 \(|i-j| \le 2\) 的点可以消除一对这个过程视作 \(i,j\) 进行匹配。

\(o(V)\) 表示 \(V\) 的奇连通块个数。

由 Tutte-Berge Formula 公式得到:一般图 \(G=(V,E)\) 的最大匹配数为 \(\dfrac{1}{2}\min\limits_{S \subseteq V} {(|V| + |S| -o(V \setminus S))} = \dfrac{1}{2}(|V|-\max\limits_{S \subseteq V} { (-|S| +o(V \setminus S))})\)

接下来只需要考虑计算 \(\max\limits_{S \subseteq V} { (o(V \setminus S)-|S|)}\)

这张图是带权的,每个点都由 \(a_i\) 个点组成,可以发现结论:对于任意的 \(i\),最优方案只存在于将 \(a_i\) 个点全部加入 \(S\) 集合,或者全部不加入。

证明:假设第 \(i\) 个点里面有 \(x(1\le x<a_i)\) 个小点加入,那么我们可以将 \(x\) 变为 \(x-1\),因为并未改变 \(i\) 与其他点的连通性,所以 \(o(V \setminus S)\) 最多变化 \(\pm 1\),而 \(-|S|\) 会增加一,所以 \(\max\limits_{S \subseteq V} { (o(V \setminus S)-|S|)}\) 是单掉不降的。

\(x=a_i\) 的时候连通性会改变,所以是另一种选择方案。

我们设 \(s_i=0/1\) 代表第 \(i\) 个点全部不选入/选入 \(S\),要求的信息就为奇连通 \(0\) 块的数量减去 \(1\) 所有位置的权值和。

我们注意到,两个 \(0\) 夹一个 \(1\) 的情况是非常不方便处理的,我们考虑避免这种情况。可以发现,把 \(1\) 改成 \(0\) 是一定不会变劣的:

证明:跟上面相似,我们考虑把 \(1\) 替换成 \(0\),表示奇数连通块为 \(O\),偶数为 \(E\),合并了左右两个连通块,讨论 \(O|O,O|E,E|O,E|E\) 四种情况后发现,\(o(V \setminus S)\) 最多变化 \(\pm 1\),而 \(-|S|\) 的增幅必定 \(\ge 1\),所以替换一定更优。

还有一个细节,就是关于 \(a_i=0\) 的处理。可以发现,把 \(a_i=0\) 的地方,选 \(s_i=0\) 不劣于 \(s_i=1\)

证明:\(s_i=0/1\) 对答案造成的影响产生于 \(i\) 左右两边 \(0\) 连通块的合并,换句话说 \(s_i=0/1\) 会产生贡献当且仅当 \(i-1\)\(i+1\) 都是 \(0\),在这个条件下,\(i-1\)\(i+1\) 是一个连通块,所以说 \(i\) 的合并是无效的。

接着就可以直接动态 dp 了:

我们设 \(f_{01/11/110/00/00'}\),五种状态(后简写为 0/1/2/3/4)分别表示结尾为 \(01\)\(11\)\(110\)\(00\) 且连通块大小为偶数,\(00\) 且连通块大小为偶数。

列出矩阵,注意要 \(a_i\) 奇数和偶数分类讨论,这里的矩阵乘法是 (max,+) 的广义矩阵乘法:

\( \begin{bmatrix}f_{0} & f_{1} & f_{2} & f_{3} & f_{4} \end{bmatrix} \begin{bmatrix}-\infty & -a_i & -\infty & -\infty & -\infty \\ -\infty & -a_i & a_i & 0 & -\infty \\ -a_i & -\infty & -\infty & -\infty & -\infty \\ -a_i & -\infty & -\infty & 0 & -\infty \\ -a_i & -\infty & -\infty & -\infty & 0\end{bmatrix} =\begin{bmatrix}f_{0}' & f_{1}' & f_{2}' & f_{3}' & f_{4}' \end{bmatrix} (a_i \mod 2 \equiv 0) \)

\( \begin{bmatrix}f_{0} & f_{1} & f_{2} & f_{3} & f_{4} \end{bmatrix} \begin{bmatrix}-\infty & -a_i & -\infty & -\infty & -\infty \\ -\infty & -a_i & a_i & -\infty & 1 \\ -a_i & -\infty & -\infty & -\infty & -\infty \\ -a_i & -\infty & -\infty & -\infty & 1 \\ -a_i & -\infty & -\infty & -1 & -\infty\end{bmatrix} =\begin{bmatrix}f_{0}' & f_{1}' & f_{2}' & f_{3}' & f_{4}' \end{bmatrix} (a_i \mod 2 \equiv 1) \)

时间复杂度 \(O(k^3 n \log n)\),空间线性,这里默认 \(n,q\) 同阶。

P6666 [清华集训2016] 数据交互

题目的答案即为所有和 \((u,v)\) 相交的路径权值和。

观察路径 \((a,b)\) 什么时候与 \((u,v)\) 有交?

发现有两种情况,\(\text{lca}(u,v) \in (a,b)\)\(\text{lca}(a,b) \in (u,v)\)

为了避免不算重,我们可以钦定第一种 \(\text{lca}(u,v) \ne \text{lca}(a,b)\)

\(A_u\)\(\sum\limits_{u \in(a_i,b_i)}w_i\)\(B_u\)\(\sum\limits_{\text{lca}(a_i,b_i)=u} w_i\)

那么与 \((u,v)\) 有交的路径权值和即为 \(A_\text{lca(u,v)} + \sum\limits_{k \in (u,v),k \ne \text{lca(u,v)}}B_k\)

\(f_u\) 为从 \(u\) 往下走最大的 \(B_u\) 的和,以及记 \(\sec\) 为次大值。

对于 \(u\)\(f_u = B_u + \max(f_v)\)

\(u\) 贡献的答案为 \(A_u + \max(f_v) + \sec(f_v)\)

然后考虑动态 dp,设 \(u\) 的重儿子为 \(\text{son}_u\)

\(g_u\) 表示答案,记 \(S_u\)\(u\) 的所有儿子构成的集合,\(mx = \max\limits_{v \in S_u,v \ne \text{son}_u} f_v, sc = \sec\limits_{v \in S_u,v \ne \text{son}_u} f_v,\)

\( \begin{bmatrix}f_{\text{son}_u} & g_{\text{son}_u} & 0 \end{bmatrix} \begin{bmatrix} B_u & -\infty & mx + B_u \\ mx + A_u & 0 & mx + sc + A_u \\ -\infty & -\infty & 0 \end{bmatrix}= \begin{bmatrix}f_{u} & g_{u} & 0 \end{bmatrix} \)

然后考虑修改,\(B_u\) 只会修改单点可以暴力修改,考虑修改 \(A_u\)

发现区间加 \(A_u\) 就等于乘上一个矩阵,然后就可以做了。

复杂度 \(O(n \log^2 n)\),这里没写 \(k^3\) 的原因是需要把矩阵拆开精细实现,空间线性。

*P5327 [ZJOI2019] 语言

第一眼会看出一个 \(O(n \log^3 n)\) 做法啊,树剖弄出来贡献矩阵然后做扫描线。

我们考虑这样一个子问题,给定点集 \(S\), 求包含 \(S\) 的生成树的最小大小。

诶诶,这不就类似于 \(S\) 的虚树吗,但是会加入一些非关键点,会把虚树压缩的链给还原。

如果你做过 P11306 [COTS 2016] 搜索树 Jelka,你应该能很快反应过来,有一个经典结论是,若干个点到根的并,就是 \(\sum \text{dep}_i\) 减去两两 \(\text{dfn}\) 相邻的 \(\text{dep}_{\text{lca}}\)

我们考虑强制选择 \(1\) 节点,最后给答案减去 \(1\) 的贡献 \(\text{dep}_{\text{lca(all)}}\) 即可。

然后考虑用线段树维护这个过程,我们按 \(\text{dfn}\) 为下标建树,然后维护区间第一个 \(u\),最后一个 \(u\),合并是 \(O(1)\) 的。

然后再考虑给一条路径做树上差分,然后最外层再做一个线段树合并就好了。

时间 \(O(n\log n)\)

P6780 [Ynoi2009] pmrllcsrms

\(C\) 分块,然后拆贡献,贡献会产生两类,分别为块内贡献,和跨块的贡献。

第一个是好维护的,重要在第二个。

我们设 \(pre_{i,j}\) 为选择块 \(i\) 的前 \(j\) 个的和,\(suf_{i,j}\) 同理,我们要求 \(\max(pre_{k+1,x}+suf_{k,y})(x+y\le C)\),这里没写 \(k\) 的边界值,懒得写。

我们注意到等价于一个等腰直角三角形,有 \(a_i,b_i\),求三角形内一点 \(a_x+b_y\) 最大值。

这个是方便维护的,因为线段树维护信息合并是 \(O(1)\) 的。

然后做完了,实现略恶心,看到题解说卡常,其实完全不卡常,最大点 2.8s。

时间 \(O(n \log n)\)

*P6199 [EER1] 河童重工

首先我们考虑上一个静态链分治,问题转化为求 \((i,j)\) 点权为 \(dis_i+dis_j+dis_2(i,j)\) 的完全图的最小生成树。

套用 Tree MST 的做法,时间 \(O(n \log^2 n)\),空间线性。

实现了 \(O(n \log^3 n)\)

P6106 [Ynoi2010] Self Adjusting Top Tree

首先我们差分答案,以 \((-\infty,-\infty)\) 为左下角把询问差分成四次。

会发现贡献有三类:与矩阵左边界相交的线段,与矩阵右边界相交的线段,被完全包含的线段。

第三类贡献直接做二维数点,第一,二类等价,只讨论第一类。

我们把 \(k\ge 0\)\(k<0\) 的线段分两次处理,假设现在处理 \(k \ge 0\)

由于线段互不相交,我们可以确定一个线段碰到直线的先后顺序。

具体来说,我们扫描线,假设 \(y=k\) 依次碰到线段 \(l_1\)\(l_p\),我们从 \(l_i\)\(l_{i+1}\) 连一条边,这个只需要在插入或者删除线段时拿 set 维护前驱后继即可。

这样形成了一张 DAG,边数是 \(O(n)\) 级别,我们可以求出来每条线段的拓扑序 \(p_i\)

我们扫描线的时候,我们拿这个拓扑序作为关键字,二分出来最后一个满足和矩阵上边界相交的线段,贡献很好计算。

时间 \(O(n \log n)\),空间线性。

*P5386 [Cnoi2019] 数字游戏

啊啊,你说得对,但是 \(O(n \sqrt n \log n)\) 可以过啊?

严格根号做法跟第十分块差不多,回滚莫队,然后每个块维护链表,查询时合并。

posted @ 2025-02-10 16:37  nullpt3  阅读(19)  评论(0)    收藏  举报