3.1——943F
943F
限时每日一题day7。忘了在 \(map<vector>\) 上二分的 \(trick\)。大致思路没问题,就差这临门一脚。
先回顾一下在 \(map<vector>\) 上二分的 \(trick\):
- 原理:存储某个数在给定序列中的所有位置,进而可以通过在对应 \(vector\) 上二分来确定满足某些性质的位置。
- 复杂度:每次查找是 \(O(log^{2}n)\)(\(map\) 一个 \(log\),二分一个 \(log\))
可以简化一下问题:划分的段数一定可转化为 2 段或者 3 段(多出来的段可合并在一起,而异或和保持不变)。
只有 2 段时,当且仅当区间异或和为 0 时一定成立。
划分为 3 段,则显然 每一段的异或和 必然为 整段的异或和,设为 \(sum\)。相当于找:
- 满足 \(k1 >= l\) 的最小的 \(k1\),使得 \(a[l到k1]\) 的异或和为 \(sum\)。
- 满足 \(k2 <= r\) 的最大的 \(k2\),使得 \(a[k2到r]\) 的异或和为 \(sum\)。
- \(k1 < k2\)
由于 \(sum\) 的数量非常多,因此可以将上述思路转化成另一种形式:
- 满足 \(k1 >= l\) 的最小的 \(k1\),使得 \(a[k1到r]\) 的异或和为 \(0\)。
- 满足 \(k2 <= r\) 的最大的 \(k2\),使得 \(a[l到k2]\) 的异或和为 \(0\)。
- \(k1 <= k2\)
这样需要存储位置的数就只可能为 \(pre\) 与 \(suf\) 数组中的每个值,是 \(O(n)\) 的。