传送门
给出(m)个查询,查询([l,r])的最大异或和
可删除线性基
每次插入值的时候就进行线性基更新,同时维护下当前二进制第i位的最后更新点
然后把查询离线,按照右区间排序
查询时,看线性基最后更新时间是否在当前的区间。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MaxBasis = 20;///二进制位数
struct Linear_Basis {
ll base[MaxBasis + 10]; bool rel; int sz;
int tim[MaxBasis];
vector<ll> Basis;/// 线性基(向量)
Linear_Basis() { memset(base, 0, sizeof(base)); rel = false; sz = 0; Basis.clear();}
void init() {
memset(base, 0, sizeof(base)); rel = false; sz = 0; Basis.clear();
memset(tim, 0, sizeof(tim));
}
bool add(ll x, int t) { //加入线性基中
for (int i = MaxBasis; i >= 0; --i) {
if (!(x >> i & 1)) continue;
if (base[i]) {if(t > tim[i]) swap(t, tim[i]), swap(x, base[i]); x ^= base[i];}
else {
base[i] = x, ++sz; tim[i] = t;
return 1;
}
}
rel = true;
return 0;
}
ll Max(int t) { //取最大
ll ans = 0;
for(int i = MaxBasis; i >= 0; i--)
if(t <= tim[i] && !(ans >> i & 1)) ans ^= base[i];
return ans;
}
} lb;
const int N = 5e5 + 5;
ll a[N], Ans[N];
struct Query{
int l, r, id;
} q[N];
int main(){
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
int m; scanf("%d", &m);
for(int i = 1; i <= m; i++) {
scanf("%d%d", &q[i].l, &q[i].r); q[i].id = i;
}
sort(q + 1, q + m + 1, [](Query &a, Query &b){ // 右区间排序
return a.r < b.r;
});
for(int i = 1, j = 1; i <= n; i++) {
lb.add(a[i], i);
for(; j <= m && q[j].r <= i; j++) Ans[q[j].id] = lb.Max(q[j].l);
}
for(int i = 1; i <= m; i++)
printf("%lld
", Ans[i]);
return 0;
}