【A】树上数据结构
P11194 [COTS 2021] 县 Županije
相邻的县的县城 到县的分割线距离一定是相等的。
那么可以设 \(f_u\) 若是县城是否合法,可以自下往上 dp。
点分树优化。
P5311 [Ynoi2011] 成都七中
点分治,若重心不是 \([l,r]\) 内的点,那么就递归 \(x\) 的分治子树询问;
否则我们在当前分治重心处理询问。这样每个询问只会被挂在一个询问重心上,记录每个点到重心路径上点的 min/max,跑 2-side 数颜色就好了。
时间复杂度 \(O(n\log ^2 n)\)。
P17141 [NOI 2026] 传送
2log:https://www.cnblogs.com/TalBana/p/21943497
1log:观察到相邻点的决策 \(x\) 相差不超过 1,那么可以只在一个点上二分。
P10805 [CEOI 2024] 加油站
边分治。
对于向上的路径:设 \(f_u\) 表示在 \(u\) 处加油的方案数,统计答案的时候要乘上子树补大小。考虑转移,从上一处加油的地方转移过来,有 \(k-(dep_v-dep_u)<w\),从 \(v\) 处进行贡献,倍增处理。
对于向下的路径:设 \(g_u\) 表示在 \(u\) 处加油的方案数,转移和上面类似,只用从祖先链上转移。需要处理第一步加油。
时间复杂度 \(O(n\log^2 n)\)。
P7126 [Ynoi2008] rdCcot
给一个连通块找代表元。
以最浅的点作为代表元,相同时取编号较小的点。
考虑每个点什么时候是代表元,因为 \(C\) 是给定的,可以预处理区间 \([L_i,R_i]\) 表示当 \([l,r]\subseteq [L_i,R_i],i\in [l,r]\) 时 \(i\) 是代表元。
那么是类似询问 \(dep_v\le dep_u,v\in O_u,v<u\) 中最大的 \(v\)。
先把 \(u\) 挂到 $\log $ 个点分树祖先上,每次查询 \(\mathrm{dis}(v,t)\le x,dep_v\le dep_u\),\(u\) 的前驱。
可以按照 \(\mathrm{dis}(v,t)\) 加入 \(v\),然后维护区间 \(dep\) min,让 \(u\) 在 \([1,u-1]\) 上二分前驱。
最后做二维偏序回答代表元数量。
离线动态图连通性
维护删除时间最大生成树。
CF2097E Clearing the Snowdrift
一定是从大到小减。
设当前全局 \(\max=x\),需要用最少的区间覆盖所有的 \(a_i\ge x\)。
对于 \(a_i\ge x\) 连边 \(i\to i+k\),边权 1;否则连边 \(i\to i+1,边权 0\)。
那么 \(1\) 到 \(>n\) 的点的最小距离即为覆盖所需代价,这其实是深度。
从大到小枚举 \(x\),然后使用 LCT 动态维护。
P8531 [Ynoi2003] 戌亥彗星
考虑对于每个 \(r\) 找到一个最小的左端点 \(l_0\),满足:存在恰好一个简单环的必要条件是 \(l\ge l_0\)。
这个东西可以使用 LCT 维护。因为只存在恰好一个简单环,所以可以另外维护一条环边。
然后是只有环上的节点可以 \(\deg>2\),我们维护了一条额外的环边,所以变成路径查询 \(\deg>2\) 的节点数量。
上面两个东西都可以双指针,找到合法左端点的最小值。
然后是连通的限制,发现由于我们限制了至多存在一个简单环,故一定有 \(|E|=|V|\) 等价于是基环树,而 \(|E|\le |V|\)。
所以其实可以维护 \(|V|-|E|\),然后给等于区间最小值的节点打记录历史和标记。
时间复杂度 \(O(n\log n)\)。
CF2237H Slime and Queries
CF1007D Ants
路径有边交就不行。
那么变成路径插入,路径查询。kosaraju。
P15246 [WC2026] 猫和老鼠
https://www.cnblogs.com/TalBana/p/19856235
toptree 相关
https://www.luogu.com/article/akkuybg1
https://www.cnblogs.com/ExplodingKonjac/p/17890636.html
AT_abc311_h [ABC311Ex] Many Illumination Plans
https://www.luogu.com.cn/article/fkkh38rg
继承重子树的背包,暴力加入轻子树中的点。然后再递归轻儿子计算。
AT_s8pc_5_h Percepts of Atcoder
P17144 [NOI 2026] 木棉
考虑 prufer 还原树的过程,那就是维护一个叶子集合,每次拉出最小的叶子,然后连接到 \(p_i\),接着 \(p_i\) 的度数减一。然后如果 \(p_i\) 的度数变成 1 了就可以加入叶子集合。
显然在 prufer 中 \(u\) 最晚的出现位置就是他变成叶子的位置。那么可以判断 \(x,y\) 谁是父亲节点。
假设 \(x\) 是 \(y\) 的儿子,考虑 \(x\) 加入叶子集合后,维护 \(c\) 表示 \(<x\) 的叶子个数。
每次会导致 \(c\) 变成 \(\max(0,c-1)\),然后 \(c\) 可能会增加 1。如果 \(\max\) 操作生效了说明 \(x\) 在这里被用了。
然后你发现如果你 \(c\) 变成 0 了以后就一定一直是 0,那直接二分一下这个位置。
序列扫描线,维护每个数的最后一次出现。
浙公网安备 33010602011771号