【笔记】数据结构选讲 2024.7.31

【模板】"动态 DP"&动态树分治(树剖)

P4719 【模板】"动态 DP"&动态树分治 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

\[\begin{bmatrix} f_{u, 0}& f_{u, 0}\\ f_{u, 1}& -\infty \end{bmatrix}\times\begin{bmatrix} f_{v, 0}\\ f_{v, 1} \end{bmatrix}=\begin{bmatrix} f_{u, 0}\\ f_{u, 1} \end{bmatrix} \]

这样可以轻易写为树剖,令 \(v=son(u)\)

[Ynoi Easy Round 2020] TEST_63(LCT)

P8265 [Ynoi Easy Round 2020] TEST_63 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

\[siz_u>2siz_v\iff \exists k, siz_u\geq 2^k>siz_v \]

维护一条链的信息:先 access 链底全改成重边,再考虑维护树链剖分(显然根据定义只会改轻 \(O(\log n)\) 条轻边)。枚举 \(k\),在平衡树上二分找到这个 \(u\),然后去检查 \(u, v\) 是不是应该变轻。

在 LCT 上维护轻子树信息是能做的。然后你维护了重链信息之后就能做了。

维护一个集合,支持增删 \(\max\),可以开两个 priority_queue,一个存下加的数,一个存下删的数。

[JOISC 2019 Day2] Two Antennas(历史最值)

#3033. 「JOISC 2019 Day2」两个天线 - 题目 - LibreOJ (loj.ac)

扫描线,试图维护历史最大值信息。对于天线 \(i\),相当于它有一个注册时间和注销时间。对于天线 \(j\),扫到它的时候会有一个合法的 \(i\) 区间可用。维护两个序列 \(a, b\),初始都是 \(-10^9\)\(i\) 注册时,将 \(a_i\) 修改为 \(-h_i\)\(j\) 扫到时,将 \(b[]\) 区间复制为 \(h_j\),然后再推平回去。维护区间 \(a_i+b_i\) 的历史最大值的最大值。绝对值符号反过来的,reverse 再做一次。

[Ynoi2002 / CTT2022] Optimal Ordered Problem Solver(修改分类)

P9061 [Ynoi2002] Optimal Ordered Problem Solver - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

所有的点,要么没有被操作过,要么在操作矩形的并的轮廓线上。

修改:轮廓线上的点做 \(x_i\) / \(y_i\) 的区间复制,外面的点暴力查找加入。

查询:轮廓线上的点截取出来数一下,外面的三维偏序。

三维偏序是 \(O(n\log^2n)\) 的,优化是容斥,拆成上方(二维)、右方(二维)、右上角(都没被修改过,可以直接做)。

[CTT2021] 简单数据结构(修改分类)

【北大集训2021】简单数据结构 - 题目 - Universal Online Judge (uoj.ac)

如果没有 3 操作而是最后输出序列,那么可以将一堆操作合并为 \(a_i\gets \min_j(a_i+ki, v_j+t_ji)\)。后者是上凸壳,说明被修改的点是始终单调递增的。

如果已经知道每个点的首次修改时间,则可以使用线段树标记维护。为了求出前者,使用整体二分。每次整体二分求一个凸壳出来,看一眼怎么修改,然后分下去。

[Hangzhou23F] Top Cluster(直径性质)

Top Cluster - Problem - QOJ.ac

权值互不相同是关键。二分答案,查询 \(1\sim v\) 的点是否与询问点距离 \(\leq d\),取到最值的点一定是一条直径的一端。

[dmopc21c8p6] Castle Building(匹配)

[DMOPC '21 Contest 8 P6 - Castle Building - DMOJ: Modern Online Judge](https://dmoj.ca/problem/dmopc21c8p6#:~:text=Initially, 1 3 4 5 7)

分讨 \(n\) 出现的位置,改写成未出现的数匹配区间的形式,尝试使用 Hall 定理,需要对所有 \(l\leq r\) 判定一个二维的东西 \(\sum a\leq\sum b\)。全体区间可以写成两行,每一行的区间互不相交。所以我们首先对每个区间都判一次 Hall 定理。然后,考虑对于一个区间 \([L,R]\),原来是对 \([l, r]\ni[L,R]\) 有容量的贡献,考虑对 \([l, r]\in[L,R]\) 的减去这个区间的容量,这样不影响判定。于是可以转成一维的东西。修改只影响 \(O(1)\) 个区间。

[NOIWC2024] 线段树(树上 dp)

P10145 [WC2024] 线段树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

会了,不想写题解啊

[Ynoi2009] rprmq1(历史最值)

P6109 [Ynoi2009] rprmq1 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

将询问拆成二区间合并的形式。以拆出的右区间为例,为了保证所有矩形加操作都有顾及,可以考虑在同一层中处理这些区间。用一棵历史最大值线段树扫过去,扫到一个分治区间中点的时候,为了保证查询不被中点前面部分影响,可以给全局加一个 \(+\infty\),放弃之前已经消失的最值(但是现在还在的矩形还留着),询问的时候再抠掉 \(+\infty\)。注意 \(+\infty\) 的选取。\(O(m\log^2n+q\log n)\)

[Hangzhou23K] Card Game(可持久化平衡树)

Card Game - Problem - QOJ.ac

\(t_i\) 为下一个与 \(a_i\) 相同的数的下标,那么:

\[ans(l, r)=\begin{cases} ans(l+1, r)+1, &t_l>r,\\ ans(t_l+1, r), &t_l\leq r. \end{cases} \]

\(l\) 从右往左扫,可持久化平衡树解决区间复制问题。

[Hefei23K] Campus Partition(树上 dp)

Campus Partition - Problem - QOJ.ac

所划分的一定是链,且链的两端是最大值与次大值(否则不优)。\(f_{u, x}\) 表示 \(u\to x\) 的链准备匹配,\(h_u\) 表示 \(u\) 子树内的答案。然后线段树合并,分类合并那两条链或者继承。

[KOI TST 2023] 택시 여행 / Taxi(点分)

택시 여행 - Problem - QOJ.ac

运行 Dijkstra 算法。

点分树,需要支持在所有点分树父亲上插入一次函数,查询单点最小值,写若干李超线段树即可。都是平凡的。

[CTT2021] 小明的树(点边容斥)

【北大集训2021】小明的树 - 题目 - Universal Online Judge (uoj.ac)

点边容斥计算连通块,只需要分开讨论每一条边什么时候给谁有贡献,需要求 \(\sum[\text{未点亮的点-边}=1]\sum[\text{点亮的点-边}]\),写成 \(\sum[a=1]\sum b\) 算了,显然 \(a=1\) 已经是最小值,所以写为 \(\sum [a=\min a]\sum b\),线段树随机维护一下就好了。修改操作甚至不需要维护树形态,而只是 \(O(1)\) 个区间加。

[2022-2023 集训队互测 Round 2] 相等树链(点分、hash)

相等树链 - Problem - QOJ.ac

点分治到重心 \(rt\)。考虑采取异或哈希判定相等,随机权值 \(c_i\)。从 \(rt\) 出发的路径,我们要选两条拼起来,观察到这两条路径拼起来在 \(T_2\) 上的路径两端点 \(\in\) 由这两条路径各自在 \(T_2\) 上组成的路径两端点(一共四个点)的集合。枚举在 \(T_2\) 上的路径两端点分别来自哪里,使用极其恶心的树上前缀异或和的 LCA 分讨随机完成。

[CF1707E] Replace(倍增)

Replace - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

重要的观察:

\[f([l, r])=\bigcup_{i=l}^{r-1}f([i, i+1]) \]

\[f^k([l, r])=\bigcup_{i=l}^{r-1}f^k([i, i+1]) \]

这样就好多了啊!

倍增:

\[f^{2^k}([x, x+1])=\bigcup_{i=l}^{r-1}f^{2^{k-1}}([i, i+1]), \text{where }[l,r]=f^{2^{k-1}}([x, x+1]) \]

任意 RMQ 算法,没了啊!

[CF1558F] Strange Sort(0/1 转化)

Strange Sort - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

枚举 \(v=1\sim n\),将 \(\leq v\) 的标记为 \(0\)\(>v\) 的标记为 \(1\),并尝试将其排序成 \(v\)\(0\)\(n-v\)\(1\),对所有时间取最大值作为答案。考虑所有 \(1\) 的位置,从右往左记为 \(x_1, x_2, \cdots, x_k\),那么 \(x_1\) 被移到正确位置的时间为

\[t_1=n-x_i+0/1 \]

\(+0/1\) 是因为有个奇偶修正的部分。

\(t_2\)\(t_1\) 一样,不过 \(x_2\) 可能会被 \(x_1\) 挡住,但如果是这样,则 \(x_2\) 一定会紧随 \(x_1\) 之后到达它的位置。

\[t_2=\max(n-1-x_2+0/1, t_1+1) \]

\[\implies t_i=\max(n-i+1-x_i+0/1, t_{i-1}+1) \]

我们要求的是

\[t_k=\max_i(n-i+1-x_i+0/1+k-i) \]

外层的 \(v\) 减少时,这些 \(t\) 是区间修改,或者平衡树都可以做。

[QOJ4815] Flower's Land(点分、树上背包)

题解 QOJ4815【Flower's Land】 - caijianhong - 博客园 (cnblogs.com)

Segbeats(势能分析)

线段树支持 1. 区间 chkmin \(v\);2. 区间和。

考虑在线段树上每个节点维护 \(max1, max2, num, sum\) 表示最大值,严格次大值,最大值出现次数,区间和。chkmin \(v\) 的操作,分类讨论:

  1. \(v\geq max1\):无影响。
  2. \(max1>v>max2\):打上标记,表示以后将所有最大值改为 \(v\),不往下递归,\(sum\) 可以维护。
  3. \(max2\geq v\):暴力向下递归。

复杂度分析:暴力向下递归之后,这个线段树区间的不同值的个数会至少减少一,总不超过 \(O(n\log n)\)

如果加上区间加操作,复杂度变为 \(O(n\log^2n)\) 但是实际表现和 \(O(n\log n)\) 差不多,但是没人会证。听说这东西常数不小。

posted @ 2024-07-31 08:30  caijianhong  阅读(121)  评论(0编辑  收藏  举报