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));
	}

}

posted @ 2023-02-09 17:28  RiverSheep  阅读(34)  评论(0编辑  收藏  举报