Ivan and Burgers
Ivan and Burgers
求\(l, r\)内异或最大值,容易想到维护线性基,但直接维护是不可取的,这时我们可以找到一种更优秀的维护方式,维护前缀线性基。
对于区间\(1, r\),只需维护一个\(p_i\)和\(pos_i\),表示\(i\)位上,数为\(p_i\),编号最大为\(pos_i\),这样我们想求\(l,r\)的线性基只用取其中\(pos_i \ge l\)的数即可。
对于\(pos_i\)可以贪心维护,在插入一个数\(x\)时,比较编号,大的留下即可。
Code
#include<cstdio>
#include<iostream>
#define IN inline
using namespace std;
const int N = 5e5 + 5;
int p[N][30], pos[N][30], n, m;
IN int read() {
int t = 0,res = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) t |= (ch == '-');
for (; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ 48);
return t ? -res : res;
}
void Insert(int id, int x) {
int g = id;
for (int i = 0; i < 26; i++) p[id][i] = p[id - 1][i], pos[id][i] = pos[id - 1][i];
for (int i = 25; i >= 0; i--) {
if ((x >> i) & 1) {
if (!p[g][i]) {
p[g][i] = x, pos[g][i] = id;
return;
}
if (pos[g][i] < id) swap(x, p[g][i]), swap(pos[g][i], id);
x ^= p[g][i];
}
}
}
int query(int id, int lit) {
int res = 0;
for (int i = 25; i >= 0; i--)
if (pos[id][i] >= lit) res = max(res, res ^ p[id][i]);
return res;
}
int main() {
n = read();
for (int i = 1, x; i <= n; i++) x = read(), Insert(i, x);
m = read();
for (int i = 1; i <= m; i++) {
int l = read(), r = read();
printf("%d\n",query(r, l));
}
}