思维题
CF708C Centroids
考虑到一个点作为根时不是重心,仅可能为其最大的子树大小超过 ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor ⌊2n⌋,使其再成为重心需从中分离出一个大小不超过 ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor ⌊2n⌋ 的最大子树,若仍然不合法即无解。
注意需要维护向下的也要维护向上的,从 u u u 到 v v v 更新时,若 u u u 的最大子树为 v v v ,则需要使用 u u u 的次大子树来更新。
树的重心
定义
1
1
1:树中所有点到某个点的距离和最小,则该点为重心。
定义
2
2
2:没有一颗子树大小超过
⌊
n
2
⌋
\lfloor\frac{n}{2}\rfloor
⌊2n⌋ 的节点。
CF1406C Link Cut Centroids
一棵树至多有两个重心,且相邻,若有两个重心 u , v u,v u,v,考虑从 u u u 中取一个叶子节点 x x x,将其接到 v v v 上。
树的重心的性质:一棵树至多有两个重心,且相邻。
CF1304E 1-Trees and Queries
考虑添加一条边后,路径仅可能为
a
→
x
→
y
→
b
a\rightarrow x\rightarrow y \rightarrow b
a→x→y→b,
a
→
y
→
x
→
b
a \rightarrow y \rightarrow x \rightarrow b
a→y→x→b,
a
→
b
a \rightarrow b
a→b 。
可以重复经过点,则对于一条长为 x x x 的路径 若 2 ∣ b − k 2|b-k 2∣b−k 即为合法。
P4374 [USACO18OPEN]Disruption P
考虑一条额外边 ( u , v , w ) (u,v,w) (u,v,w) 的影响,成了一颗基环树,对于这个环上的任意一条边均可被 ( u , v , w ) (u,v,w) (u,v,w) 替代,即原树 u → v u\rightarrow v u→v 路径上的边,树链剖分维护最小值即可。
CF1187E Tree Painting
a n s = ∑ s z u ans=\sum sz_u ans=∑szu 。根的位置决定各子树大小,换根 dp 即可。
当根节点 u → v u\rightarrow v u→v, a n s ← a n s − s z v + ( n − s z v ) ans\leftarrow ans-sz_v+(n-sz_v) ans←ans−szv+(n−szv)。
P3698 [CQOI2017]小Q的棋盘
贪心的取,考虑先取一条最长链,每走一步代价为 1 1 1,价值为 1 1 1 。剩下 x x x 步,考虑在取该链的过程中向外拓展取 y y y 个点的代价为 2 y 2y 2y,每个点代价为 2 2 2 ,价值为 1 1 1,令 y = ⌊ x 2 ⌋ y=\lfloor\frac{x}{2}\rfloor y=⌊2x⌋ 。
最近公共祖先
洛谷P3938 斐波那契
观察发现若节点 x , y x,y x,y ,满足 y y y 是 x x x 的父亲, w i w_i wi表示节点 i i i 的标号, f f f 为斐波那契数列,则 w x − w y = max { f ∣ f i < w x } w_x-w_y=\max\{f|f_i<w_x\} wx−wy=max{f∣fi<wx},用通俗的语言来讲就是, x x x, y y y 的标号相差一个斐波那契数,满足该斐波那契数是小于 w x w_x wx 的最大斐波那契数。
考虑优化(qwq?),查找小于 w x w_x wx 的最大斐波那契数,即查找小于 w x w_x wx 的第一个斐波那契数,考虑用 upper_bound + greater < int > 或者 lower_bound - 1 解决。
生成树
洛谷P1340 兽径管理
考虑到有很多周需要处理,不采用优先级队列,用普通的数组 + 排序。
- 一次性读取所有数据,按边权排序,每次遍历数组,只取用周数符合条件的即可。
- 每次读取一个数据,使用 lower_bound 插入。
暴力就是每次都求一遍最小生成树,考虑优化。
考虑正向加边的影响,对于一次生成树中未选用的边无论如何在后续都不会用到,对于图还未联通前,直接输出 − 1 -1 −1。
考虑反向删边的影响,对于待删除的边未在已有生成树中使用到的,可直接删除,对于图不连通后,直接全输出 − 1 -1 −1。
UVA1395 苗条的生成树 Slim Span
Kruskal 暴力,按边权排序后,枚举遍历存边数组的起点下标,即可遍历所有生成树。
树上差分
点差分
边差分
洛谷P6869 Putovanje
题目未要求在线,考虑树上差分,考虑算出每一条边的经过次数,再枚举每一条边得出最小价格。
边权不好处理,对于边权 w a → b w_{a\rightarrow b} wa→b,考虑将其映射到点权 w b w_b wb 。
对于差分操作,使
x
∼
y
x\sim y
x∼y 路径上的每一条边边权增加
k
k
k,记
d
i
d_i
di 为差分数组,
z
=
lca
(
x
,
y
)
z=\operatorname{lca}(x,y)
z=lca(x,y)。
d
x
←
d
x
+
k
,
d
y
←
d
y
+
k
,
d
z
←
d
z
−
2
k
d_x\leftarrow d_x+k,\space d_y\leftarrow d_y+k,\space d_z\leftarrow d_z-2k
dx←dx+k, dy←dy+k, dz←dz−2k
统计类
洛谷P5002 专心 OI - 找祖先
对于每一个点,记它有
k
k
k 个子树,各个子树的大小为
w
i
w_i
wi 。
可以发现,这个点对答案的贡献为:各个子树之间的点对 + 各个子树与父亲节点的点对 + 父亲节点与各个子树的点对 + 父亲节点与父亲节点的点对,即
(
∑
i
=
1
k
∑
j
=
1
i
−
1
w
i
w
j
)
+
(
2
∑
i
=
1
k
w
i
)
+
1
(\sum_{i=1}^{k}\sum_{j=1}^{i-1}w_iw_j)+(2\sum_{i=1}^{k}w_i)+1
(i=1∑kj=1∑i−1wiwj)+(2i=1∑kwi)+1观察发现
j
j
j 这一维被反复使用且循环范围单调递增,考虑前缀和维护,时间复杂度
O
(
n
)
O(n)
O(n) 。
洛谷P1351 联合权值
对于每一个距离为 2 2 2 的点 i i i, j j j 一定存在一个唯一的中间点 k k k(因为是树),考虑枚举每一个点 k k k。
对于每一个点
k
k
k,答案即为
∑
i
=
1
s
∑
j
=
1
i
−
1
w
i
×
w
j
\large\sum_{i=1}^{s}\sum_{j=1}^{i-1}w_i\times w_j
i=1∑sj=1∑i−1wi×wj
s
s
s 为点
k
k
k 的的儿子数量,
w
i
w_i
wi 为
k
k
k 的第
i
i
i 个儿子的权。
显然直接枚举的时间复杂度为
O
(
n
2
)
O(n^2)
O(n2),考虑玄学方法 ,观察发现
j
j
j 这一维被反复使用且循环范围单调递增,考虑前缀和维护,记
p
r
e
i
=
∑
i
=
1
n
w
i
pre_i=\sum_{i=1}^{n}w_i
prei=∑i=1nwi,答案即为
∑
i
=
1
s
w
i
×
p
r
e
i
−
1
\large\sum_{i=1}^{s}w_i \times pre_{i-1}
i=1∑swi×prei−1
对于每一个
w
i
w_i
wi,仅会用到
p
r
e
i
−
1
pre_{i-1}
prei−1,还可以压掉一维(零维?)。
另类做法:dfs 时传递爷爷,每个爷爷和孙子之间会产生贡献,各个兄弟之间也会产生贡献。
最大点权独立集
洛谷P2607 骑士
基环树 模板题, n n n 个点, n n n 条边的图,定义保证有不超过一个环,考虑把每个连通块的环断开,然后进行树形动态规划
最大点权独立集问题,各个点的选择之间存在矛盾,断环,分别在断开这条边的两端点 l l l, r r r 进行 没有上司的舞会,统计该连通图的答案即为 max ( g l , g r ) \max(g_l,g_r) max(gl,gr), f i f_i fi 为选点 i i i 可得的战斗力最大值, g i g_i gi 为不选 i i i 可得的战斗力最大值
注:对于重复利用的变量,使用前的初始化以及统计答案要在下一次使用之前进行,本人因此 WA 了 ∞ \infty ∞ 次,该题初始化 f i = w i f_i=w_i fi=wi, g i = 0 g_i=0 gi=0, w i w_i wi 为点 i i i 的战斗力