点分树:维护每颗子树内所有相同颜色点到根距离的最小值+次小值。
再维护一个全局的最小答案。都可以套multiset(注意multiset直接删除一个值时是将所有这个值都删掉,只删除一个要用指针)
拆位&点分树:
对于每个分治中心,维护管辖子树内0和1的个数及距离和以及它的每个儿子结点子树内0和1的个数及距离和(容斥用)。
单个四元组可以看做一堆石子,它的石子数就是它的字典序大小(每次可以拿任意个)。同样一条路径可以看做Nim游戏。
问题转成了求石子数异或和为0的总路径数,点分治即可。
关键在于求四元组 ( a , b , c , d ) (a,b,c,d) (a,b,c,d)的字典大小:
第一位不同:
∑ t = 1 a − 1 ∑ i = 1 t ∑ j = 1 t gcd ( i , j ) \quad \sum\limits_{t=1}^{a-1} \sum\limits_{i=1}^t \sum\limits_{j=1}^t\gcd (i,j) t=1∑a−1i=1∑tj=1∑tgcd(i,j)
= ∑ t = 1 a − 1 ∑ i = 1 t φ ( i ) ⌊ t i ⌋ 2 =\sum\limits_{t=1}^{a-1}\sum\limits_{i=1}^t\varphi (i)\lfloor\dfrac {t}{i}\rfloor^2 =t=1∑a−1i=1∑tφ(i)⌊it⌋2
可以对 1 ≤ a ≤ 1000 1\leq a\leq 1000 1≤a≤1000统一 n \sqrt n n预处理。
第二位不同:
∑ t = 1 b − 1 ∑ i = 1 a gcd ( t , i ) \quad \sum\limits_{t=1}^{b-1}\sum\limits_{i=1}^a \gcd(t,i) t=1∑b−1i=1∑agcd(t,i)
= ∑ t = 1 min ( b − 1 , a ) φ ( t ) ⌊ b − 1 i ⌋ ⌊ a i ⌋ =\sum\limits_{t=1}^{\min(b-1,a)}\varphi (t)\lfloor\dfrac {b-1}{i}\rfloor\lfloor\dfrac{a}{i}\rfloor =t=1∑min(b−1,a)φ(t)⌊ib−1⌋⌊ia⌋
第三位不同:
∑ i = 1 c − 1 gcd ( b , i ) \sum\limits_{i=1}^{c-1}\gcd(b,i) i=1∑c−1gcd(b,i)
= ∑ i ∣ b φ ( i ) ⌊ c − 1 i ⌋ =\sum\limits_{i|b}\varphi (i)\lfloor\dfrac{c-1}{i}\rfloor =i∣b∑φ(i)⌊ic−1⌋
第四位不同:
max ( d − 1 , 0 ) \max(d-1,0) max(d−1,0)
题解
总询问点数 ≤ 500000 ≤ 500000 ≤500000明示建虚树。
对于每个点,首先在点分树内算出单点贡献,再建出虚树容斥,对于每条存在重复计算点的边 ( u , v ) (u,v) (u,v):
二分出中点 z z z,使得 r u − d i s ( u , z ) = r v − d i s ( v , z ) r_u-dis(u,z)=r_v-dis(v,z) ru−dis(u,z)=rv−dis(v,z)。
那么在 u , v u,v u,v共同覆盖的区域内从 u u u一边出发:跨过 z z z后 v v v比 u u u优,未跨过时 u u u比 v v v优。删去 z z z能覆盖的范围的点(这部分被算了2次)。
p.s
为了避免 z z z在边上的情况,可以在所有边上都建一个虚点。
点分治:每个子集直接记录记录距离分治中心 k k k的点数 f k f_k fk,构造 f k f_k fk的生成函数直接卷积就得到了经过分治中心长度为 k k k的路径数,找到素数直接统计即可。
什么? f k f_k fk和子集卷积会算重? 2 k 2k 2k里面只有 2 2 2是质数,特判一下即可。
求中位数直接套路二分把 ≥ m i d \geq mid ≥mid的边权看做1, < m i d <mid <mid的看做-1,找是否存在一条总权 ≥ \geq ≥的边。
处理子数信息需要单调队列和前缀和优化使得总复杂度降到 O ( n log 2 n ) O(n\log ^2 n) O(nlog2n)(二分套点分治)。
点分树,每个分治中心维护一个单调栈( d d d递减,颜色不同,并维护时间戳)
每次查询 x x x暴力跳点分树,跳到 y y y时,二分出单调栈内最小的满足 d ≥ d i s t ( x , y ) ) d\geq dist(x,y)) d≥dist(x,y))的点的颜色,取时间戳最大的。
小结
求解有根树问题基本上都可以多个 log \log log转成求解无根树所有点的答案。
路径问题都可以套点分治。
在线问题点分树,离线下来点分治。
点分治维护信息往往可以优化到 n log n n\log n nlogn或线性,存在一些常见套路(可以套很多东西(单调队列,BIT…),也有很多东西可以套点分治(二分,拆位))。
注意复杂度。
点分治序也是个好东西。