题目简述
思路
看到查询最大异或和,果断想到线性基,又看到了区间操作,果断想到线段树。
于是就有了线段树套线性基。
对于插入操作,我们可以对线段树上对应的点的线性基直接插入。
对于询问操作,我们可以将区间内的线性基并在一块查询。
然后代码就写完了,吸吸氧就过了。
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e4 + 10;
int N , M;
struct LB {
int P[40];
LB() { memset(P , 0 , sizeof P); }
void Insert(int k) {
for(int i = 31; i >= 0; i--) {
if(!(k & (1 << i))) continue;
if(!P[i]) {
P[i] = k;
return;
}
k ^= P[i];
}
}
int Query() {
int res = 0;
for(int i = 31; i >= 0; i--) res = max(res , (res ^ P[i]));
return res;
}
void Merge(LB X) {
for(int i = 31; i >= 0; i--)
if(X.P[i])
Insert(X.P[i]);
}
};
struct Node {
int l , r;
LB v;
} Tree[MAXN * 4];
void PushDown(int p) {
Tree[p].v.Merge(Tree[p * 2].v);
Tree[p].v.Merge(Tree[p * 2 + 1].v);
}
void Build(int p , int l , int r) {
Tree[p].l = l;
Tree[p].r = r;
if(l == r) return;
int Mid = l + r >> 1;
Build(p * 2 , l , Mid);
Build(p * 2 + 1 , Mid + 1 , r);
PushDown(p);
}
void UpDate(int p , int pos , int k) {
if(Tree[p].l == pos && Tree[p].r == pos) {
Tree[p].v.Insert(k);
return;
}
int Mid = (Tree[p].l + Tree[p].r) >> 1;
if(pos <= Mid) UpDate(p * 2 , pos , k);
else UpDate(p * 2 + 1 , pos , k);
PushDown(p);
return;
}
LB Query(int p , int l , int r) {
if(l <= Tree[p].l && Tree[p].r <= r) {
return Tree[p].v;
}
LB res;
int Mid = (Tree[p].l + Tree[p].r) >> 1;
if(l <= Mid) res.Merge(Query(p * 2 , l , r));
if(r > Mid) res.Merge(Query(p * 2 + 1 , l , r));
return res;
}
signed main() {
ios::sync_with_stdio(false);
cin >> N >> M;
Build(1 , 1 , M);
for(int i = 1 , op , l , r; i <= N; i++) {
cin >> op >> l >> r;
if(op == 1) {
UpDate(1 , l , r);
}
else {
cout << Query(1 , l , r).Query() << endl;
}
}
return 0;
}