ZROI 19.08.01 树上数据结构

1.总览

  • LCT
  • 链分治(树剖)
  • 点/边分治

2.点分治

  • 一棵树,点有\(0/1\),多次修改,询问最远的两个\(1\)距离。

建出点分树,每个子树用堆维护:①最远的\(1\)距离;②它的每个儿子的①堆顶;

全局维护每棵子树②堆最大的两个值,每次修改暴力改就可以。

时间复杂度\(O(n \log^2n)\)(基本动态点分都是\(\log^2\)以上的复杂度……然而仍然随便过\(10^5\),小常数可能性微存?)。


  • 一棵树,点有点权,每次询问距离一个点不超过\(k\)的点权和。

每个点维护一个深度数据结构(这里树状数组就可以),询问的时候子树直接查,父亲递归上去。

每个点对每个儿子单独维护一个树状数组,因为计算的时候要差分。


  • 一棵树,度数不超过\(20\),支持修改点权,求带权重心。

考虑重心在树上转移的过程,如果不是到父亲,显然是走到\(size_y>\frac{size_x}{2}\)的一个子树。

可以用点分树优化这个过程。

每次扫一下所有儿子,找到最优的,直接跳到分治中心递归即可。

由于重心是凸的,可以保证正确性。


考虑查询的时候,在点分树上找到最浅的一个点\(y\),满足这个点被保留\([l,r]\)后被\(x\)的连通块包含,则所有\([l,r]\)间的点都在\(y\)的子树里。

对于以\(y\)为分治中心的每个点\(i\),维护从\(i\)到\(y\)路径上编号最大和最小的点\(\max_i,\min_i\)。

发现点\(i\)在连通块内的充要条件是\([\min_i,\max_i] \subseteq [l,r]\),转化成了经典二维数点问题。

3.链分治

  • \(n\)个点的树,每条边可以切断或不切断,求\(1\)号点连通块大小恰好为\(k\)的方案数,对ntt模数取模。\(n \leq 10^5\)。

一个比较显然的暴力是直接背包,每对点会在\(lca\)处产生一次复杂度,总复杂度\(O(n^2)\)。

观察dp式子\(f_{x,j}=\prod_{y \in son_x}^{\sum_k=j}(f_{y,k}+[k=0])\),发现很像一个卷积。

考虑链分治,树上轻儿子\(size\)和是\(O(n\log n)\)级别。

所以对于一条重链,可以先递归求出它链上所有轻儿子的生成函数,然后就变成了序列上问题,这个可以分治fft解决。总复杂度\(O(n\log^3n)\),不过常数很小。


著名毒瘤题。(我写这题的时候splay和treap都被卡常了,最后换了压缩trie才过)

比较naive的想法是根号分治+\(\log\)数据结构。

发现对于每个大点,修改次数均摊\(O(\sqrt n)\)次,询问次数只有均摊\(O(1)\)次,用分块代替\(\log\)数据结构,可以做到\(O(n\sqrt n)\)。

换一种思路,对每个点维护轻儿子,则不在这个集合里的只有重儿子,本身和父亲。修改的时候暴力跳重链就行了。

单次修改\(\log^2n\),询问\(\log n\)。(实际上有一个\(\log\)的做法)


比较naive的想法是离线建出操作树,问题变成了求链上叉积最大值。然而直接维护凸包是\(\log^3 n\)的(树剖+线段树/set+凸包上二分)。

观察在重链上跳的过程,发现除了最后一次,每次都是重链上的一个前缀,那么可以离线询问,对每条重链直接暴力维护前缀凸包,两部分都是\(\log^2n\)。


  • \(n\)个点的树,\(q\)次操作,支持修改点权,询问最大权联通子图。\(n, q \leq 10^5\)。

考虑序列上怎么做,发现就是一个经典的线段树题。

把它搬到树上,发现就是一个动态dp,做完了。

4.LCT

  • 动态dp:只要满足dp式子具有可合并性,即,两个操作复合之后可以变成同样形态,只是系数不同的操作,就可以用动态dp维护。

  • \(n\)个人,\(0\)~\(n-1\),每个人有一个\(a_i\)。初始有一个\(x=0\),按顺序依次执行每个人,可以选择把\(x\)变成\((x+a_i) \mod n\),最后\(x\)获胜。每个人的策略都是:只有变了\(x\)必胜,且不变\(x\)不必胜时,他才会变。\(q\)次操作,每次修改某个\(a_i\),输出操作后谁会获胜。

每轮游戏只会有一个人动手,且动手前后一定是\(i-a_i => i\)。

如果\(i\geq a_i\),则\(i\)向\(i-a_i\)连边,整个结构形成了一个森林。

所有叶节点为\(f_i=1\),中间节点为\(\max(0, 1-\sum_{j\in son_i}f_j\),lct维护动态dp即可。


  • \(n\)个点的点仙人掌,边带权,\(m\)次操作,每次修改一条边权或询问两点间最大流。

最大流=最小割。

最小割如果是环边,就一定会把环上的最小值删掉,不妨把它删掉并把它的权值加到环上的其他边上,lct维护即可。

圆方树也可以做,合理设置边权即可。


  • \(n\)个点的树,\(q\)次操作:增加点权,翻转路径(权值),询问路径和/最大值/最小值。

建两棵splay分别维护权值和形态,保证中序遍历一一对应,修改直接在权值splay上做就好了。


发现修改操作和lct中的换根操作一模一样,直接lct维护就行了。需要一个树状数组来维护额外信息。


  • 有\(A,B,C\)三个点集,各有\(n_A,n_B,n_C\)个点。其中\(A\cup B,A\cup C\)分别构成两棵树,\(A\)内部没有边。随机\(i,j\),删除\([B_1,B_i],[C_1,C_j]\),问\(A\)仍然联通的概率。\(n_i\leq 10^5\)。

枚举\(i\),显然\(j\)具有单调性,可以双指针。对于\(AB\)间的每条边,边权设为删除时间,加入\(AC\)边的时候删除\(AB\)间最早删除的边即可,lct随便维护。

不知道为什么这种水题讲了那么久。

原文地址:https://www.cnblogs.com/suwakow/p/11375070.html

时间: 2024-08-30 18:15:17

ZROI 19.08.01 树上数据结构的相关文章

ZROI 19.08.03 DP入门

\(n\)个点,要求连一棵树,设点\(i\)的度数为\(d_i\),则其贡献为\(f(d_i)\mod 59393\),其中\(f(x)\)是一个\(k\)次多项式.最大化总贡献.\(n\leq 3000, k\leq 10, a_i\leq 50\). 对于任意一种度数序列,都可以生成一棵对应的树. 每个点度数\(\geq 1\),\(-1\)后等于\(n\)个点分\(n-2\)个度数. \(O(n^3)\)dp:\(f_{i,j}\)表示前\(i\)个点,度数和为\(j\)的最优解,转移的时

ZROI 19.08.04模拟赛

传送门 写在前面:为了保护正睿题目版权,这里不放题面,只写题解. "这应该是正睿OI历史上第一次差评破百的比赛." "这说明来正睿集训的人越来越多了." "我很不能理解差评,因为在比赛开始前就有超过\(40\)个差评了." 天祺鸽鸽nb! A "这题标程是线性的,可是为什么没有出\(5\times 10^6\)呢?因为spj要带个\(\log\),这样就T了." \(100pts:\) 打表观察发现有解当且仅当\(\sum k

ZROI 19.08.12模拟赛

传送门 写在前面:为了保护正睿题目版权,这里不放题面,只写题解. "我发现问题的根源是大家都不会前缀和."--敦爷 A 敦爷spj写错了,差点把蒟蒻swk送走 \(50pts:\) 考虑不输出方案怎么做.显然是树形dp. 设\(f_{i,j,\{0/1/2\}}\)表示\(i\)的子树中,有\(j\)条链,根节点状态为:\(\{\)没选\(/\)选了向下的一条链\(/\)选了向下的两条链\(\}\)的最优解. 对于一棵子树,开始时只考虑根节点,依次合并每个儿子.合并时需要枚举父亲和儿子

ZROI 19.07.28 序列数据结构/jk

写在前面 dls:"我不会数据结构,但是APIO的数据结构场我写了,还是蛮简单的." T1 CF643G Sol: 有一个\(O(n\log^2n)\)的做法:假设将区间排好序,取六等分点,则答案一定覆盖了若干点,求区间第\(k\)大即可. 然而会TLE 定义绝对众数为区间中出现超过一半的数. 有一个经典的做法求绝对众数,然而它要在保证有解的时候才保证正确性. 维护当前答案和出现次数,遇到相同则\(+1\),不同则\(-1\),降为\(-1\)的时候就把当前解替换. 显然如果有解的话,

ZROI 19.08.02 杂题选讲

给出\(n\)个数,用最少的\(2^k\)或\(-2^{k}\),使得能拼出所有数,输出方案.\(n,|a_i|\leq 10^5\). 显然一个绝对值最多选一次.这个性质非常强. 如果所有都是偶数,可以直接除以\(2\). 否则\(1\)或\(-1\)必须选,暴力枚举选哪个然后递归,每层去重,发现最多只会递归\(\log a\)次.总复杂度\(O((n+a)\log n)\),等价于线段树上区间长度总和. \(n\)个数,每次可以花费\(1\)的代价给某个数\(+1\)或\(-1\),问变成不

ZROI 19.08.11模拟赛

传送门 写在前面:为了保护正睿题目版权,这里不放题面,只写题解. dlstql,wsl A \(10pts:\) \(a=100,T=100\),对每个排列构造一个反的,一步到位即可. \(20pts:\) \(a=50\),构造\(1\)和所有元素交换的排列,实现交换\((v,u)\)可以令两者分别与\(1\)交换,选择排序即可. \(40pts:\) \(a=30\),构造前\(25\)个元素与\(1\)交换的排列,另有一个排列交换前\(25\)个与后\(25\)个元素. \(a=20\)时

ZROI 19.08.05模拟赛

传送门 写在前面:为了保护正睿题目版权,这里不放题面,只写题解. A \(21pts:\) 随便枚举,随便爆搜就好了. \(65pts:\) 比较显然的dp,设\(f_{i,j,k}\)表示在子树\(i\)中,两个赞助商分别选了\(j,k\)个的最优解. 对枚举的上下界卡的紧一点,按照树上背包的聚合分析,复杂度是\(O(n^3)\)的,可以通过. \(100pts:\) 观察数据范围可以发现,这题的子树大小限制可以抽象成一个经典的网络流模型. 跑一个最大费用流就好了. 我写丑了,每个点拆了\(5

ZROI 19.08.03 分治与离线

经典问题,给一张图,支持加边/删边/询问两点连通性. 离线统计边权(删除时间),lct维护最大生成树即可. 也可以按时间分治,维护一个可回退并查集即可. 主定理 很好用,但是记不住. 有一种简明的替代方式:画一棵递归树,考虑层数和每层的节点数(线段树分析.jpg) 分治时递归和处理中心的顺序可以是任意的,可以按照具体情况选择,以 简化复杂度. 快速排序的期望复杂度: \[T(n)=\frac{1}{n}\sum_{i=1}^n[T(i-1)+T(n-i)]+n-1=\frac{2}{n}\sum

ZROI 19.08.10模拟赛

传送门 写在前面:为了保护正睿题目版权,这里不放题面,只写题解. A \(20pts:\) 枚举操作序列然后暴力跑,复杂度\(O(6^n)\). \([50,80]pts:\) 枚举改成dfs,每层操作后还原.复杂度\(O(3^n)\). 全0或全1可以直接返回. 写法优秀可以过\(80pts\). \(100pts:\) 类似非递归fft的写法,bitrev后可以位运算优化. 最下面四层可以预处理,复杂度\(O(3^{n-4})\). 然后疯狂卡常就完事了( 然而由于swk人菜常数大,明明所有