xor 线性基
线性基求并
前缀线性基
考虑这样一个问题
对于一个数列,求 \([l,r]\) 中的数的异或最大值,强制在线。
如果 \([l,r]\) 是全集那么我们很容易使用线性基得到答案,考虑在线段树上维护线性基,但是这显然很蠢(复杂度会多一个 \(\log{n}\))。
考虑对每个 \(i\) 维护 \([1,i]\) 倒着插入的线性基,简单来说就是我们想要尽可能考虑 \(i\) 的数作为基。这并不需要真的倒着插入,只需在从前往后加入每个 \(i\) 的时候贪心判断即可。
具体的流程
-
复制 \(i-1\) 的线性基
-
将 \(a[i]\) 插入
-
插入时如果该位置已经有值,替换成 \(a[i]\)
struct Linear_Base{
int a[31][2];
void insert(int x, int pos) {
for (int i = 30; i >= 0; i--) {
if (x & (1 << i)) {
if (!a[i][0]) {
a[i][0] = x;
a[i][1] = pos;
break;
} else {
if (a[i][1] < pos) swap(a[i][0], x), swap(a[i][1], pos);
x ^= a[i][0];
}
}
}
}
}xxj[maxn];
考虑查询,如果对于某一位最近的都比 \(l\) 小,那么我们就不能使用这一位。例查询最大值:
for (int i = 30; i >= 0; i--) {
if (xxj[r].a[i][1] >= l) {
if ((ans ^ xxj[r].a[i][0]) > ans) {
ans ^= xxj[r].a[i][0];
}
}
}
习题
luogu3292(比什么点分治香多了)