題意:給你一個數組,有兩種操作,一種區間xor一個值,一個是查詢區間xor的結果的種類數
對於一個給定的區間,我們可以通過求解線性基的方式求出結果的種類數,而現在只不過將其放在線段樹上維護區間線性基。
#include <bits/stdc++.h>
using namespace std;
struct L_B {
long long d[31];
void init() {
memset(d, 0, sizeof(d));
}
bool insert(long long val) {
for (int i = 30; i >= 0; i--)
if (val & (1 << i)) {
if (!d[i]) {
d[i] = val;
break;
}
val ^= d[i];
}
return val > 0;
}
int cnt() {
int res = 0;
for (int i = 30; i >= 0; --i) {
if (d[i])res++;
}
return 1 << res;
}
};
struct node {
L_B lb;
int lazy, w;
int l, r;
} t[200004 * 4];
node merge(const node n1, const node n2) { //線性基合併
node ret = n1;
for (int i = 30; i >= 0; i--) {
if (n1.lb.d[i])ret.lb.insert(n1.lb.d[i]);
if (n2.lb.d[i])ret.lb.insert(n2.lb.d[i]);
}
ret.lb.insert(n1.w ^ n2.w);
ret.w = n2.w;
return ret;
}
int a[200004];
void pu(int rt) {// 線段樹更新
int l = t[rt].l;
int r = t[rt].r;
int lazy = t[rt].lazy;
t[rt] = merge(t[rt << 1], t[rt << 1 | 1]);
t[rt].l = l, t[rt].r = r, t[rt].lazy = lazy;
}
void build(int rt, int l, int r) {
t[rt].l = l, t[rt].r = r, t[rt].lazy = 0;
t[rt].lb.init();
if (l == r) {
t[rt].w = a[l];
} else {
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
pu(rt);
}
}
void pushdown(int rt) {
if (t[rt].lazy == 0)return;
t[rt << 1].lazy ^= t[rt].lazy;
t[rt << 1 | 1].lazy ^= t[rt].lazy;
t[rt << 1].w ^= t[rt].lazy;
t[rt << 1 | 1].w ^= t[rt].lazy;
t[rt].lazy = 0;
}
void update(int rt, int l, int r, int xo) { // 區間更新
if (t[rt].l >= l && t[rt].r <= r) {
t[rt].lazy ^= xo;
t[rt].w ^= xo;
} else {
pushdown(rt);
int mid = (t[rt].l + t[rt].r) >> 1;
if (l <= mid)update(rt << 1, l, r, xo);
if (r > mid)update(rt << 1 | 1, l, r, xo);
pu(rt);
}
}
void query(int rt, int l, int r, node &ans) {
if (t[rt].l >= l && t[rt].r <= r) {
ans = merge(ans, t[rt]);
} else {
pushdown(rt);
int mid = (t[rt].l + t[rt].r) >> 1;
if (l <= mid) {
query(rt << 1, l, r, ans);
}
if (r > mid) {
query(rt << 1 | 1, l, r, ans);
}
}
}
int main() {
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
build(1, 1, n);
while (q--) {
int op, l, r, k;
scanf("%d", &op);
if (op == 1) {
scanf("%d%d%d", &l, &r, &k);
update(1, l, r, k);
} else {
scanf("%d%d", &l, &r);
node ans;
ans.lb.init();
ans.w = 0;
query(1, l, r, ans);
printf("%d\n", ans.lb.cnt());
}
}
}