区间线性基
概述
首先,区间线性基是可以用猫树在 \(O(n\log ^2n)/O(\log ^2n)\) 的时间内处理的,当然这和本文没有任何关系。
本文将介绍如何在 \(O(n\log n)/O(\log n)\) 的时间复杂度内维护区间线性基。
贪心地维护带权线性基
考虑贪心,直接在插入元素 \(x\) 时,如果线性基 \(b\) 中 \(b_i\) 时有值的,并且权值(即下标)优于 \(x\) 的权值,那么将 \(x\) 和 \(b_i\) 交换,并继续尝试插入此时的 \(x\)(即原先的 \(b_i\))。
容易证明这是对的。
区间线性基
\(\forall i\in [1,n]\),维护包含 \([1,i]\) 的带权线性基,权值为下标。
查询时查 \([1,r]\) 的线性基,跳过所有权值小于 \(l\) 的值。
// ABC233Ex
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=4e5+9;
const int lgV=60;
struct Basis{
ll b[lgV];int w[lgV];
inline void Insert(ll x,int k){
for(int i=lgV-1;~i;i--){
if(~x>>i&1) continue ;
if(k>w[i]){
swap(b[i],x),swap(w[i],k);
if(!x) break ;
}
x^=b[i];
}
}
inline bool Find(ll x,int k){
for(int i=lgV-1;~i;i--) if(w[i]>=k&&(x>>i&1)) x^=b[i];
return !x;
}
}b[N];
int n,q;
ll a[N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
#define endl '\n'
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=b[i-1];
b[i].Insert(a[i],i);
}
while(q--){
int l,r;ll x;
cin>>l>>r>>x;
if(b[r].Find(x,l)) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}

浙公网安备 33010602011771号