P10218 [省选联考 2024] 魔法手杖 题解
P10218 [省选联考 2024] 魔法手杖 题解
首先套路二分答案 \(ans\),则要求:\(\exists x,S\subseteq T,\sum\limits_{i\in S}b_i\le m,\min\{\min\limits_{i\in S}\{a_i+x\},\min\limits_{i\not\in S}\{a_i\oplus x\}\}\ge ans\)
这个条件太复杂,我们需要将条件转化为几个简单的条件:
-
\(\forall i,a_i+x\ge ans\)
-
\(\sum\limits_{a_i\oplus x<ans}b_i\le m\)
这里只有 \(x\) 是不确定的,第二个条件相当于每个 \(a_i\) 对一些 \(x\) 的取值产生了贡献而这些贡献是在 \(\oplus\) 的情况下进行的,我们可以用 trie 进行维护。
如果对值域贡献是以 \(\pm\) 进行的,那么应该使用动态开点权值线段树,如果是以 \(\oplus\) 进行的,那么应该使用 trie。正如黄洛天在“L-树”一题中说到trie其实是一种动态开点权值线段树。
具体方法如下:每次插入一个数 \(a_i\),从高到低枚举每一位
-
若 \(ans\) 这一位为 \(1\),将与 \(a_i\) 这一位相同的子树代价加上 \(b_i\),递归处理与 \(a_i\) 这一位不同的子树。
-
若 \(ans\) 这一位为 \(0\),直接递归与 \(a_i\) 相同的子树。
最后遍历每个节点,看是否存在 \(x\ge ans-\min{a_i}\),使得 \(x\) 的加标记 \(\le m\) 即可。
这样复杂度 \(\mathcal O(nk^2)\) 且常数较大。
对于位运算的求解转判断,我们可以抛弃二分而采用从高位到地位尝试 \(1\) 的方式。
从高位到地位枚举每一位,尝试将 \(ans\) 这一位赋为 \(1\),并将未处理的部分视作 \(0\),按照上述方式处理 \(b_i\) 的贡献后进行检测。由于检测是遍历所有的 \(\mathcal O(nk)\) 个点,复杂度还是 \(\mathcal O(nk^2)\) 但常数较小。
接下来是如何快速检测,发现只有叶子节点是合法的,且对于其中没有 \(a_i\) 的节点,加标记不再发生变化,这可以直接用一个值存储,那么每次检测只需要遍历 \(a_i\) 所在的节点,复杂度变为 \(\mathcal O(nk)\)。
注意这道题使用了__int128,比较卡常,需要加上读入优化。

浙公网安备 33010602011771号