3.18 —— cf div3 900 G
G. wxhtzdy ORO Tree
每日一题 day4
这次做得超级顺,虽然思路想了很久,但是 code 特别顺畅,本以为 debug 会非常困难,没想到写完后直接一遍过了。这也是我觉得自己具备的优点—— code时能够保持清醒的思路,遇到模棱两可的情况时也要竭尽全力想明白之后再写,这样写完之后很多时候都会完全避免 debug 过程。还需要继续保持。
核心思路就是要反着算贡献。先将路径序列化,然后对于每个二进制位,得到在序列中该位上最左侧1与最右侧1的位置,它们之间的位置取 \(z\) 一定能让前后缀在该位上的贡献都是 \(1\),否则最多只会有一个 \(1\)(序列全 \(0\) 时特判,其他情况都是恰好一个 \(1\))。于是就可以得到 \(O(\log A)\) 个区间,我们需要求的就是被最多区间包含的点对应的包含区间数量。
在这里卡了挺久,最开始想的是直接用线段树维护区间加与区间最大值,但是建线段树的复杂度就是 \(O(n)\) 的,在多查询里肯定不行。之后突然发现一个性质:在所有区间端点中,必然存在某个点是被最多区间包含的点。 而区间数量是 \(O(\log A)\),于是我们只需要对每个区间端点暴力计数被多少个区间包含就行了,复杂度 \(O(\log^{2} A)\)。
找到每个二进制位对应的区间左右端点需要结合分类讨论与树上倍增,复杂度 \(O(\log n)\)。
总复杂度 \(O(q * \log A * \log n + q * \log A * \log A)\)。

浙公网安备 33010602011771号