Loading

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,比较卡常,需要加上读入优化。

posted @ 2025-02-09 20:01  lupengheyyds  阅读(27)  评论(0)    收藏  举报