[差分] [位运算] P6623 [省选联考 2020 A 卷] 树
posted on 2024-04-26 05:25:44 | under | source
首先找规律可以发现,\(k+1,k+2,k+3...\) 的二进制下第 \(k\) 位有周期性质。
具体来说,循环节形如 \(1...10...0\),其中 \(1\) 段和 \(0\) 段大小都为 \(2^k\)。
考虑按位枚举 \(k\)。\(u\) 会向其 \(i=1,2,3...\) 级祖先贡献 \(2^k\),当且仅当 \(a_u+i\) 第 \(k\) 位是 \(1\)。
结合先前结论,则呈现为对若干段区间贡献的形式。转换为差分,就是在 \(a+i*2^k\) 级祖先上异或 \(2^k\)。其中 \(a\) 是循环节中第一个 \(1\) 出现的位置。
观察到所有 \(a+i*2^k\bmod 2^k= a\),也就是说会在深度 \(dep_p \bmod 2^k= b\) 的点 \(p\) 上异或 \(2^k\)。其中 \(a,b\) 可以算出来。
定义 \(s_{k,i}\) 表示深度模 \(2^k=i\) 的贡献异或和,于是在 \(s_{k,b}\) 上异或 \(2^k\) 就能 \(O(1)\) 修改了。
但是这样的话,算 \(u\) 答案时,可能会算入其它不在 \(u\) 子树内的点的贡献,怎么办?
考虑一个经典套路:\(\rm dfs\) 过程中,\(u\) 子树内的值 \(=\) 退出 \(u\) 的值 \(-\) 准备进入 \(u\) 的值。
复杂度 \(O(n\log n)\),相当优秀。
至于我原来的SB做法是 \(O(nlog^3 n)\) 的,这里不讨论它。

浙公网安备 33010602011771号