RT, node.p[i]是当前节点线性基, node.n2g[i]代表node.p[i]由奇数/偶数个元素合成,其余应该不难懂,本地运行随机测试数据约6s
#include<bits/stdc++.h>
using namespace std;
int read () {
int a = 1, x = 0;
char c = getchar();
while (!isdigit(c)) a = (c == '-' ? -a : a), c = getchar();
while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return a * x;
}
void write (int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + 48);
}
struct node {
int p[30], lb, rb, lz;
bool n2g[30];
node *ls, *rs;
node () {
ls = rs = NULL;
lb = rb = lz = 0;
memset(p, 0, sizeof(p));
memset(n2g, 0, sizeof(n2g));
}
};
void insert (int *p, bool *n2g, bool bn2g, int x) {
for (register int i = 29;i >= 0;i--) {
if (x & (1 << i)) {
if (!p[i]) {
p[i] = x;
n2g[i] = bn2g;
break;
}
x ^= p[i];
bn2g ^= n2g[i];
}
}
}
void insert (int *p, int x) {
for (register int i = 29;i >= 0;i--) {
if (x & (1 << i)) {
if (p[i]) x ^= p[i];
else {
p[i] = x;
break;
}
}
}
}
node *build(int lb, int rb, int *a) {
node *newnode = new node;
newnode -> lb = lb;
newnode -> rb = rb;
if (lb != rb) {
int mid = (lb + rb) >> 1;
newnode -> ls = build(lb, mid, a);
newnode -> rs = build(mid+1, rb, a);
for (register int i = 0;i < 30;i++) newnode -> p[i] = newnode -> ls -> p[i], newnode -> n2g[i] = newnode -> ls -> n2g[i];
for (register int i = 0;i < 30;i++) insert(newnode -> p, newnode -> n2g, newnode -> rs -> n2g[i], newnode -> rs -> p[i]);
}
else insert(newnode -> p, newnode -> n2g, 1, a[lb]);
return newnode;
}
int newp[30], p[30];
bool n2g[30];
void apply (node *cur, int v) {
for (register int i = 0;i < 30;i++) {
newp[i] = (cur -> p[i]) ^ (cur -> n2g[i] ? v : 0);
n2g[i] = cur -> n2g [i];
cur -> n2g[i] = cur -> p[i] = 0;
}
for (register int i = 0;i < 30;i++) insert (cur -> p, cur -> n2g, n2g[i], newp[i]);
}
void pushdown (node *cur) {
if (cur -> lz) {
cur -> ls -> lz ^= cur -> lz;
apply (cur -> ls, cur -> lz);
cur -> rs -> lz ^= cur -> lz;
apply (cur -> rs, cur -> lz);
cur -> lz = 0;
}
}
void modify (node *cur, int lb, int rb, int x) {
if (cur -> lb == lb && cur -> rb == rb) {
cur -> lz ^= x;
apply (cur, x);
}
else {
pushdown (cur);
int mid = (cur -> lb + cur -> rb) >> 1;
if (lb <= mid) modify (cur -> ls, lb, min(rb, mid), x);
if (rb > mid) modify (cur -> rs, max(mid+1, lb), rb, x);
for (register int i = 0;i < 30;i++) cur -> p[i] = cur -> ls -> p[i], cur -> n2g[i] = cur -> ls -> n2g[i];
for (register int i = 0;i < 30;i++) insert(cur -> p, cur -> n2g, cur -> rs -> n2g[i], cur -> rs -> p[i]);
}
}
void query (int *ans, node *cur, int lb, int rb) {
if (cur -> lb == lb && cur -> rb == rb) {
for (register int i = 0;i < 30;i++) insert(ans, cur -> p[i]);
}
else {
pushdown(cur);
int mid = (cur -> lb + cur -> rb) >> 1;
if (lb <= mid) query(ans, cur -> ls, lb, min(rb, mid));
if (rb > mid) query(ans, cur -> rs, max(mid+1, lb), rb);
}
}
node *root;
int n, m, a[50005];
int main () {
n = read(), m = read();
for (register int i = 1;i <= n;i++) {
a[i] = read();
}
root = build(1, n, a);
int opt, l, r, x;
while (m--) {
opt = read(), l = read(), r = read(), x = read();
if (opt == 1) modify(root, l, r, x);
else {
int ans = 0;
for (register int i = 0;i < 30;i++) p[i] = 0;
query(p, root, l, r);
for (register int i = 29;i >= 0;i--) {
if ((ans ^ p[i] ^ x) > (ans ^ x)) ans ^= p[i];
}
write (ans ^ x);
putchar('\n');
}
}
}