DS 24.12
*代表笔者能自己做出来的题。
放个题单。
2024/12
P9678 [ICPC2022 Jinan R] Tree Distance
一年多前就想写的题,然后今年 T4 被支配对类问题薄纱,然后回来做。
支配关系是显然的,就是 \((l_1,r_1)\) 支配 \((l_2,r_2)\) 的条件是 \(l_2 \le l_1 < r_1 \le r_2\) 并且 \(\text{dist}(l_1,r_1) \le \text{dist}(l_2,r_2)\)。
考虑把所有支配对扒出来,首先给拍一个点分治上去,然后 \((x,y)\) 会存在一个使其不同子树的根 \(rt\)。
然后对于 \(u\) 只需要找到满足 \(x \ne u,\text{dist}(x,rt) \le \text{dist}(u,rt)\) 的 \(u\) 的前驱后缀就行。
每一层产生 \(O(n)\) 个支配对,总共产生 \(O(n \log n)\),求完弄下来做一遍二维数点。
支持负权边要麻烦一点,可能要加个维护前驱后继的东西做一下。
总时间复杂度 \(O(n \log^2 n + q \log n)\)。
P5611 [Ynoi2013] D2T2
直接做感觉是几乎不可做的。
然后发现,可以 \(O(n^2)\) 处理出来整个序列的所有 \([L,R]\) 的答案。
考虑分治,每次分两半,两半维护 \(f_{i,j}\) 代表区间 \([a_i,a_j]\) 的答案,合并显然是可以归并的。
\(T(n) = T(\dfrac{n}{2})+O(n^2) = O(n^2)\)。
所以考虑分块,每 \(B\) 个数划一块,然后 \(O(B^2 \times \dfrac{n}{B})\) 处理出每个块的所有可能答案,每次查询散块显然可以 \(O(B)\) 处理,然后遍历整块合并答案。
\(B\) 取 \(\sqrt n\),时间复杂度 \(O(n \sqrt n)\),空间被卡了,离线下来就好了。
P10540 [THUPC 2024 决赛] 古明地枣的袜子
问题第一步转化为单点加,后缀 \(\max\)。
考虑裂开所有在一个点修改的操作,然后题目的约束条件等价于存活 \([l,r]\) 的位置,然后求全局最大后缀和。
这显然是 P5611 的弱化,直接套过来改个块长就行。
【UNR #4】己酸集合
问题等价于求一条直线下的点个数,即半平面数点。
考虑把 \(k\) 从小到大排序,维护一个在确定斜率 \(k\) 下所有点的偏序关系。
很容易发现答案发生变化的斜率 \(k\),肯定是两两点连线后的某一条直线的斜率。
这两点在斜率自小到大遍历时,当斜率超过这两点间斜率时,这两个点的偏序关系就会发生变化。
可以发现,偏序关系最多变化 \(O(n^2)\) 次。
维护这个偏序关系后,答案显然是满足二分性的。
考虑把所有这种变化点对提取出来,这里有 \(O(n^2)\) 个修改,又发现答案很好 \(O(1)\) 合并,参考 P5611 的做法, 把分块后每一块分开处理,查询时每个块二分答案。
时间 \(O(n \sqrt q \log n)\)。
*P5047 [Ynoi2019 模拟赛] Yuno loves sqrt technology II
简单题,但是还是写了好久。
二次离线莫队板子,不说了。
*P8969 幻梦 | Dream with Dynamic
发现这几个操作是没有什么技巧可言的,考虑暴力维护。
直接维护一个 \(f_i\) 代表 \(i\) 进去能得到多少。
进行一次 popcount 后值域是 \(O(\log V)\) 的,所以 \(f\) 大小为 \(O(\log V)\)。
所以线段树每个节点暴力维护 \(f\),总复杂度 \(O(n \log n \log V)\)。
P10107 [GDKOI2023 提高组] 树
虽然说感觉把这个题归到 DS 栏有点扯,但是还是归进来了。
看的题解的倍增差分做法。
讲一个大概思路,发现贡献是可差分的,按 dfs 序给每个深度排序,维护每个点 \(f_{i,x}\) 代表向下跳 \(2^i\),\(x\) 子树的对应前缀的所有节点产生的贡献。
这个显然是好维护的,设 \(pre_x\) 为 \(x\) 在这一层的前缀,维护 \(g_{i,x}\) 代表从 \(x\) 出发跳 \(2^i\) 次 dfs 序最大的儿子得到的节点,特殊地,若 \(x\) 没有儿子,\(g_{0,x}=pre_x\)。
然后维护一个 \(num_{i,x}\) 代表 \(x\) 左下区域,即 \(dfn_u \le low_x\) 的所有节点有多少个点权第 \(i\) 位等于 \(1\)。
然后转移时 naive 的,就不写了。
时空复杂度 \(O(n \log n)\),感觉比较标准,但是我太菜了没见过这种东西。
P9970 [THUPC 2024 初赛] 套娃
为什么我不会。。。。。
首先一个关键结论是,一个序列极短的子区间并且 \(\text{mex}\) 为 \(x\) 的个数是 \(O(n)\) 级别的,我们称这些区间为关键区间。
对于一个关键区间 \([l,r]\),肯定有 \(a_l \ne a_r\),我们假定 \(a_l > a_r\)。
那么,加入 \(a_l,a_r\) 后答案发生了变化,也就是说,\(\text{mex}(l+1,r-1)=a_r -1\)。
所以说,对于任意一个 \(l\),其对应的 \(r\) 只有一个,反之也亦然。
所以总数是小于等于 \(2n\) 的,得证。
知道了这个结论之后,后面的比较简单。
考虑一个区间的存在 \((l_1,r_1,l_2,r_2,k)\),表示 \(k\) 的存在在 \(x\in [l_1,r_1],y \in [l_2,r_2]\) 造成贡献,求出来后拿个扫描线做一遍。
最后考虑如何求这个东西。
维护一个点左边的最右同点权出现下标 \(L_i\),倒叙扫一遍删除每个点,删除 \(a_i\) 本质是对 \(L_i\) 右边取 \(\min\)。
由于 \(\text{mex}\) 具有单调性,所以可以拿个 ODT 方便地维护。
时间 \(O(n\log n)\)。
「JOISC 2016 Day 3」回转寿司
为什么我还是不会。。。
分块,每个块加入 \(x\) 会把最大值弹出去,维护一下每个块里面的数和每个块加入过的数。
然后就做完了,时间 \(O(q\sqrt n\log n)\)。
*P9388 [THUPC 2023 决赛] 先人类的人类选别
参考回转寿司,每次塞进去一个数。
考虑把区间查询拆成前缀查询,然后发现前缀查询是简单的,拿个主席树维护前 \(k\) 大,然后和一棵值域线段树同时二分。
时空复杂度 \(O(n\log n)\)
P7603 [THUPC2021] 鬼街
神奇 trick。
如果 $\sum\limits_{i=1}^n a_i = w, \max\limits_{i-1}^k a_i \ge \left \lfloor \dfrac{w}{k} \right \rfloor $。
那么对每个质数维护一个堆,设 \(w\) 为监视器 \(x\) 的阈值,\(s\) 为 \(x\) 的质因子个数,然后每次如果闹鬼次数到达了 \(\left \lfloor \dfrac{w}{s} \right \rfloor\),那么就暴力更新这个堆,并更新阈值。
考虑这么做为什么是对的,每次阈值都至少会变为原来的 \(\dfrac{s-1}{s}\),所以复杂度是对的。
时间复杂度 \(O(nk \log n \log V)\),\(k\) 为质因子个数。
*P10856 【MX-X2-T5】「Cfz Round 4」Xor-Forces
感觉还是比较显的。
容易发现发现,一个区间异或上一个数和某个这个区间的平移区间异或上另一个数相同。
比如 \([1,2,3,4]\) 异或 \(2\) 得到 \([3,0,1,6]\),与 \([5,6,7,8]\) 异或 \(6\) 相等。
然后就可以考虑线段树维护,每个点维护 \(f_{u,i}\) 代表 \(u\) 所在的区间异或上 \(i\) 的答案。
由于上面说的性质,所以每一层的答案都是长度级别的,大于长度的可以在另一块找到答案。
答案合并时 \(O(1)\) 的,信息合并总共是 \(O(n \log n)\)。
总时空复杂度 \(O(n\log n)\)。
*P11390 [COCI 2024/2025 #1] 教师 / Učiteljica
好几个月前模拟赛考过的题,那一场这个题写假荣获 0pts。
时隔几个月,看到了这个题。
这个题直接做是困难的,所以考虑容斥,容斥完了发现就是个矩形面积并的板子,直接拍上去就好。
时间 \(O(n2^k\log n)\)。
P11024 [COTS 2020] 定序 Redoslijed
什么东西,好像以前见过的来着。
考虑倒着维护操作,每次可以选一个操作的条件是这个区间 \([l_i,r_i]\) 的每个数要不被覆盖过要不为 \(c_i\),发现每次选一个可以拍上去的操作一定不会变劣。
这样得到了一个 \(O(nm)\) 的暴力做法。
做一个很神奇的东西,我也不知道怎么想出来的:
- 把每个操作拆到线段树区间上,记拆了 \(cnt_i\) 个区间。
- 如果一个区间有颜色的地方经一次操作后(或是初始状态)全是同一种颜色,把当前区间的所有颜色为 \(c_i\) 的 \(cnt_i\) 减一。
- 如果一个区间经操作后全部被以后的操作覆盖,就把当前区间的所有 \(cnt_i\) 减一,但是要除去上一种已经减过的 \(c_i\) 不减。
- 如果 \(cnt_i\) 变为 \(0\),塞到队列里面,然后取出后把 \([l_i,r_i]\) 覆盖。
这样复杂度是对的,因为每个节点最多只会遍历两次挂在上面的操作,总复杂度 \(O(n \log n)\),空间线性。
*P10833 [COTS 2023] 下 Niz
让人无语。
第一眼看到这个题,这不是 [THUPC 2024初赛套娃] 吗?
让后把那个代码复制过来,改了两下就完了。
最后写的常数有点大,一个点 1.01s 卡了半个小时打表过的。
无语。
*P4755 Beautiful Pair
有点套路的题。
看到计算点对数量,容易想到扫描线或者分治。
前者不是很方便做,考虑后一个。
直接 cdq 写起来不是很方便,考虑每次把区间的 \(\max\) 提取出来,设位置是 \(p\),遍历左右两个区间小的区间算贡献,这个贡献是一个二维数点的形式,离线下来做扫描线,接着继续分治。
扫描线的点是 \(O(n \log n)\) 的,总时间 \(O(n \log^2 n)\)。
P11288 [COTS 2017] 模板 Z1
题目看起来还是很典,还是不会。
容易确定每个点的上界,拿个线段树做一下区间取 \(\min\) 就好。
考虑对每个上界 \(x\) 做离散化后的 dp,有三种转移:
- \(dp_{i-1,j} \to dp_{i,i}\),代表第 \(i\) 位选到上界。
- \(dp_{i-1,j} \times x \to dp_{i,j}\),代表第 \(i\) 位任意选。
- \(dp_{i,j} := 0(j<L_i)\),代表满足区间必须要有一个 \(x\) 的限制。
这个东西只需要维护全局加,全局乘,前缀赋值为 \(0\),拿个指针扫一遍最大前缀外加打两个 tag 就行。
值得注意的是,对于一个限制 \((l,r,0)\),应该直接把 \(a_{l \to r}\) 赋值为 \(0\),不参与 dp。
*「BZOJ3489」A simple rmq problem
找不到题目链接,给个 becoder 链接。
很弱智的题,考虑每个数的贡献是 \(l\in [pre_i+1,i],r \in [i, suf_i-1]\),其中 \(pre_i,suf_i\) 代表 \(a_i\) 上一个以及下一个出现的下标。
然后这个是个矩形的形式,套上来一个树套树就没了。
时间空间 \(O(n \log^2 n)\)。
*P6018 [Ynoi2010] Fusion tree
传统套路题。
首先考虑一个套路,维护每个点的所有儿子的信息。
其次考虑一个套路,从低位往高位建一棵 Trie 来支持全局 \(+1\),全局异或,插入与删除。
然后这个题就做完了,复杂度 \(O(n\log n)\)。
P10800 「CZOI-R1」卡牌
原问题是一个四维的形式,不太能做。
考虑降维。
我们枚举 \(d\),发现随着 \(d\) 的减小,限制会不断增强,具体来说,当 \(d\) 取到一定的值时,\(a,b,c\) 会有一个下界,这个下界我们记为 \(sa_d,sb_d,sc_d\)。
这样每个点 \((a,b,c)\),贡献为 \(\min(sa_a,sb_b,sc_c)\)。
这样问题就转化为了三维的带点权问题。
考虑继续降维。
我们继续枚举 \(c\),发现随着 \(c\) 的减小,\(a,b\) 也会有一个越来越强的下界,接着我们发现,随着 \(b\) 的减小,\(a\) 还是会有一个下界。
具体来说,我们钦定 \(a/b/c\) 为最小值,然后跑一遍,会发现这个最小值还是对另外两维的下界限制。
由于这种限制是不断增强的,所以枚举一维,拿指针扫一下另外两维,用个前缀和处理一下贡献就做完了。
时空复杂度 \(O(n)\)。
*P11307 [COTS 2016] 建造费 Pristojba
菠萝板子题,但是讲一下怎么做。
具体算法是维护若干连通块,每次每个连通块连最小的那条边。
这个最多进行 \(O(\log n)\) 轮,考虑一轮怎么做。
每次拿个线段树维护不同颜色的最小值,次小值,每次 \((x,l,r)\) 查询 \([l,r]\) 的值,如果最小值的颜色等于 \(x\) 的颜色,就选次小值,否则选最小值。
时间 \(O(n \log^2 n)\)。
后记:鸣谢 yzq 教我写维护最小次小值的小常数写法,不过我的 \(\min \to mx\) 写法把他污染了。
P7739 [NOI2021] 密码箱
有点无语,想到最后一步被卡住了,看了题解豁然开朗。
首先,这个东西直接维护显然是不好维护的,直接考虑上个矩阵维护。
考虑加入一个 \(a_i\) 的贡献。
\( \begin{bmatrix} a' \\ b' \end{bmatrix} = \begin{bmatrix} 0 & 1 \\ 1 & a_i \end{bmatrix} \begin{bmatrix} a \\ b \end{bmatrix} \)
接着考虑 W 操作,可以构造出矩阵满足这个操作:
\( \begin{bmatrix}0 & 1 \\ 1 & a_k \end{bmatrix} = \begin{bmatrix}1 & 1 \\ 0 & 1 \end{bmatrix} \begin{bmatrix}0 & 1 \\ 1 & a_k+1 \end{bmatrix} \)
接着考虑 E 操作。
首先考虑最后一项减一,然后加两个 1。
容易构造出来矩阵,应该乘上以下矩阵:
\( \begin{bmatrix}1 & -1 \\ 0 & 1 \end{bmatrix}\begin{bmatrix}0 & 1 \\ 1 & 1 \end{bmatrix} \begin{bmatrix}0 & 1 \\ 1 & 1 \end{bmatrix} = \begin{bmatrix}0 & -1 \\ 1 & 2 \end{bmatrix} \)
然后就不会做了。
看了题解,哦,原来另外一种情况是同一个矩阵啊,这么傻逼(流汗黄豆),这个把 \(a_k\) 拆开成看结果是否一样,不多说了。
维护时简单的,时间 \(O(kn \log n)\),常数感觉比较大,不过最大点只跑了 700ms 上下,不太懂题解是怎么被卡常的。
*P11306 [COTS 2016] 搜索树 Jelka
一棵二叉树是 BST 的充要条件是中序遍历的权值升序。
\(O(n \log^2 n)\) 的做法是显然的,因为每次修改只会影响这个点到根的路径的答案,倍增更新一下就好。
考虑 \(O(n \log n)\) 做法,发现不满足要求的点是若干条到根的路径取并集。
这个东西是很套路化的,把所有点按 \(dfn\) 排序后,求出 \((\sum \text{dep}_u) - (\sum \text{dep}_{lca(s_i,s_{i+1})})\),这个拿个 set 动态维护贡献就好。
总时间 \(O(n\log n)\),空间线性。
*P11262 [COTS 2018] 题日 Zapatak
一眼盯出来一个主席树上面哈希二分,然后发现自己是唐氏。
我们考虑维护区间所有数的和以及平方和,每次不同的那一对可以直接求出来,然后判一下区间的哈希值是不是相同。
复杂度 \(O(n)\)。
P7323 [WC2021] 括号路径
我不会做啊啊啊。
发现如果存在两条边 \((a,u,w),(b,u,w)\),\((a,b)\) 会有一条合法的括号路径。
发现这样的括号路径是可以对一个集合两两间都满足的,所以把这些东西拿个队列赛一下,用并查集和一个哈希表合并到一起。
时间理论 \(O(n)\)。
*P4314 CPU 监控
现在看很板的题目。
我们考虑给每个点维护一个向量,代表最大值和历史最大值,然后每次修改相当于乘上一个 \((\max,+)\) 矩阵。
由于有个区间赋值,发现这个向量还需要加个 \(0\)。
设 \(a',b'\) 为区间最大值,历史最大值。
加 \(k\):
\( \begin{bmatrix} a' \\ b' \\ 0 \end{bmatrix} = \begin{bmatrix} k & -\infty & -\infty \\ k & 0 & -\infty \\ -\infty & -\infty & 0 \end{bmatrix} \begin{bmatrix} a \\ b \\ 0 \end{bmatrix} \)
赋值为 \(k\):
\( \begin{bmatrix} a' \\ b' \\ 0 \end{bmatrix} = \begin{bmatrix} -\infty & -\infty & k \\ -\infty & 0 & k \\ -\infty & -\infty & 0 \end{bmatrix} \begin{bmatrix} a \\ b \\ 0 \end{bmatrix} \)。
然后就做完了,时间复杂度 \(O(n \log n)\),空间线性。
P4848 崂山白花蛇草水
神经病,一眼猜到可能是 KDT,然后不会,这种 KDT 的板子题是不是脑阔有包。
不过看到题解有篇四分树,上次看到这东西还是半年前了,没想到这东西真的有用。
说到底还是数据造太水了。
时间 \(O(n^2)\) 以上,空间不会算。
[ARC063F] すぬけ君の塗り絵 2
之前模拟赛考过的题目,现在找到原题了,这个题场上是学校自己造的数据然后一车贪心飞过去。
考虑先按 \(x_i\) 排序,按 \(y_i\) 排序是同样的,再跑一遍即可。
发现答案一定不小于 \(2\max(H,W)+2\),所以说其他矩形要取到最大值一定跨过中线,这里我们计算跨过纵坐标的中线。
那么我们维护每一个 \(i\) 对答案纵坐标的约束,如果 \(y_i \le \dfrac{H}{2}\),那么也就是说 \((x_i,y_i)\) 在下半部分,那么约束条件是把纵坐标往 \(y_i\) 上面逼,因为这样才有可能跨过中线,也就是说约束区间 \([l_i,r_i]\) 是 \([y_i,H]\),反之,若点在上半平面,则约束区间是 \([0,y_i]\),对于 \((i,j)\) 产生的答案,就是 \(2(x_j - x_i + |\bigcap\limits_{l=i}^{r}[l_i,r_i]|)\),扫描线 + 单调栈维护 \(\min\limits_{k}^i r_i - \max\limits_{k}^i l_i + x_k\)。
时间复杂度 \(O(n \log n)\),空间线性。
P3247 [HNOI2016] 最小公倍数
难评的题目。
首先题目等价于路径上 \(\max a_i = A,\max b_i = B\)。
乍一看是不好做的,想不出来什么 \(\log\) 复杂度,考虑根号。
把边分块,按 \(a\) 升序排序,每次遍历到一个块的时候把 \(a\) 在这个块区间的询问提取出来。
先把这个块以前的整块按 \(b\) 重新排序,因为前面的 \(a\) 已经没用了,把查询也按 \(b\) 排序,然后我们用个指针扫一遍查询,扫的同时加入 \(b\) 边。
然后处理这个块的散块边,每个查询都暴力遍历一遍看能不能加,能加的话就暴力加入,查询完再撤销,拿个按秩合并并查集维护一下连通信息。
时间 \(O(km \sqrt q)\),\(k\) 为反阿克曼函数的常数。
*P8959 「CGOI-3」灵气
这能上黑?
离线维护时间轴的线段树,然后拿个拓扑排序 + 可持久化线段树合并简单做一下就好。
时间 \(O(n \log n)\)。
P8528 [Ynoi2003] 铃原露露
做完感觉,自己是弱智,为什么不会这种套路题。
考虑数对 \((x,y)\) 以及 \(z=\text{lca}{(x,y)}\) 对答案造成的影响。
- \(a_x < a_z < a_y\),不形成约束
- \(a_x < a_y < a_z\),\(l\in [1, a_x],r \in [a_y,a_z]\) 的区间不合法。
- \(a_z < a_x < a_y\),\(l \in[a_z, a_x],r \in [a_y, n]\) 的区间不合法。
然后这些不合法的区间是一个矩阵的形式,只需要维护矩阵加,矩阵为 \(0\) 数量,扫描线维护区间历史等于 \(0\) 的数量即可。
但是这样修改的矩阵太多了,考虑减少,发现对于一个固定的 \(\text{lca} = u\) 来言,\(a_x\) 的前驱后继 \(y(\text{lca}(x,y)=u)\) 一定是约束最强的,所以只需要考虑这些,于是拿一个树上启发式合并做一下,总共矩阵个数是 \(O(n \log n)\) 级别。
总时间 \(O(n \log^2 n + q \log n)\),空间 \(O(n \log n)\)。
*P11191 「KDOI-10」超级演出
这个题反正很无语,调了半个多小时以为假了,然后瞄了一眼题解发现做法是对的,然后哦哦我是傻逼。
DAG 一看就是不好维护什么东西的,所以考虑暴力。
维护 \(t_i\) 表示 \(i\) 退场需要的最大的 \(l\)。
发现这个维护是很简单的,直接阈值分治,大的每次更新,小的每次暴力。
然后做一个区间带颜色二维数点就完了。
时间 \(O(n \sqrt n)\),空间线性。
P6782 [Ynoi2008] rplexq
本来是不想做的,不过看到 yzq 做了跟着做。
首先直接做肯定是不好做的,直接按度数根号分治。
对于度数 \(\le B\) 的节点,做一个用 \(O(\sqrt n) - O(1)\) 平衡的二维数点。
对于度数大的节点,提取出前 \(B\) 大的重儿子,跟着跑上面的二维数点,剩下的点跑离散莫队。
这个题最难的地方在于线性空间的实现。
时间 \(O(n \sqrt n)\),空间 \(O(n)\)。
P7470 [NOI Online 2021 提高组] 岛屿探险
首先考虑全局的查询该怎么做。
把数对按 \(b_i\) 升序排序,询问按 \(d_i\) 升序排序。
对于一个 \(d\) 数对可以划为两类,一类 \(b_i > d\),另一类反之,而且随着 \(d\) 从小变大,这个分界的指针是单向移动的。
接下来分类处理:
第一个集合查询 \(a_i \oplus c \le d\) 的个数,这个方便用 Trie 解决。
第二个集合查询 \(a_i \oplus c \le b_i\) 的个数,这个跟第一个集合的维护方法是类似的,或者说某种意义上对偶的。
答案可以拆开,然后区间版本弄上去一个线段树分治。
时间 \(O(n \log n \log V)\),空间 \(O(n \log V)\)。
*[ABC282Ex] Min + Sum
我不好评价了。
静态数对问题,大题思路是分治或者扫描线。
感觉分治比较好处理,因为有个区间 \(\min\),直接考虑最小值分治,每次遍历小的那部分,这个显然有二分性,二分一下就做完了
时间 \(O(n \log^2 n)\),空间 \(O(n \log n)\)。
*P9665 [ICPC2021 Macao R] Colorful Tree
这能上黑?
首先是一个关于直径的结论,就是两对直径 \((u_1,v_1),(u_2,v_2)\) 合并,产生的新直径在这四个点选两个之中。
对于这个题,我们对于每一种颜色维护一个同色的直径,然后再用个东西把这些同色直径合并起来。
发现我们要维护这个半群信息的单点修改和全局查,考虑用一个线段树维护。
值得注意的是,异色直径合并时,同色对产生的贡献不算入答案,但是同色对产生的两个端点是可以作为新直径的两个端点的。
还需要上一个 ST 表实现 \(O(1)\) 查询两点距离。
一定一定一定他妈要注意最多有 \(q+1\) 个节点。
时空复杂度 \(O(n \log n)\)。

浙公网安备 33010602011771号