博客:
https://blog.csdn.net/qaq__qaq/article/details/53812883
https://blog.sengxian.com/algorithms/linear-basis
模板:
#include<bits/stdc++.h>
#define ll long long
#define MAXN 10005
using namespace std;
int t,n,q;
ll k,tmp;
struct L_B
{
ll b[65],p[65],gx[65],base[65];
int cnt,flag;
L_B()
{
memset(gx,0,sizeof(gx));
memset(p,0,sizeof(p));
memset(b,0,sizeof(b));
cnt=flag=0;
for(int i=0;i<=62;i++)
base[i]=1ll<<i;
}
inline bool insert(ll x)//向线性基中插入元素
{
for(int i=62;i>=0;--i)
if(x&base[i])
{
if(b[i])
x^=b[i];
else
{
b[i]=x;
return true;
}
}
flag=1;//可异或得到0
return false;
}
ll get_max()//求最大异或值
{
ll ret=0;
for(int i=62;i>=0;--i)
if((ret^b[i])>ret)
ret^=b[i];
return ret;
}
ll get_min()//求最小异或值
{
if(flag)
return 0;
for(int i=0;i<=62;++i)
if(b[i])
return b[i];
return 0;
}
inline void rebuild()//重构 找第k小的前置步骤
{
for(int i=62;i>=1;--i)
if(b[i])
for(int j=i-1;j>=0;--j)
if(b[i]&base[j])
b[i]^=b[j];
for(int i=0;i<=62;++i)
if(b[i])
p[cnt++]=b[i],gx[cnt-1]=i;
}
ll kth(ll k)//找第k小
{
if(flag)
--k;
if(k==0)
return 0;
ll ret=0;
if(k>=base[cnt])
return -1;
for(int i=0;i<=cnt-1;++i)
if(k&base[i])
ret^=p[i];
return ret;
}
ll getindex(ll v)//看v是异或和第几小
{
ll ans=0;
if(flag)
++ans;
for(int i=cnt-1;i>=0;i--)
if(v&base[gx[i]])
ans+=base[i];
return ans;
}
void merge(L_B &n2)//把线性基n2 内的元素 逐一插入到线性基n1 中
{
flag|=n2.flag;
for(int i=0;i<=62;++i)
if(n2.b[i])
insert(n2.b[i]);
}
};
int main()
{
L_B lis;
int n;
scanf("%d",&n);
ll tmp;
for(int i=0;i<n;i++)
{
scanf("%lld",&tmp);
lis.insert(tmp);
}
printf("%lld\n",lis.get_max());
return 0;
}
维护区间[l,r]的线性基:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
int b[maxn][35],pos[maxn][35],base[35];
inline bool insert(int h,int x)//维护区间[1,h]内的线性基
{
for(int i=0;i<=30;i++)
b[h][i]=b[h-1][i],pos[h][i]=pos[h-1][i];
int tmp=h;
for(int i=30;i>=0;i--)
{
if(x&base[i])
{
if(b[h][i])
{
if(pos[h][i]<tmp)
{
swap(pos[h][i],tmp);
swap(b[h][i],x);
}
x^=b[h][i];
}
else
{
b[h][i]=x;
pos[h][i]=tmp;
return 1;
}
}
}
return 0;
}
int get_max(int l,int r)//求区间[l,r]内的最大异或值
{
int ans=0;
for(int i=30;i>=0;i--)
if(pos[r][i]>=l&&(ans^b[r][i])>ans)
ans^=b[r][i];
return ans;
}
int main()
{
for(int i=0;i<=30;i++)
base[i]=1ll<<i;
int t;
scanf("%d",&t);
int n,m,op,l,r,ans=0;
while(t--)
{
ans=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&op);
insert(i,op);
}
for(int i=0;i<m;i++)
{
scanf("%d",&op);
if(!op)
{
scanf("%d%d",&l,&r);
l=(l^ans)%n+1;
r=(r^ans)%n+1;
if(l>r)
swap(l,r);
ans=get_max(l,r);
printf("%d\n",ans);
}
else
{
scanf("%d",&l);
l^=ans;
insert(++n,l);
}
}
}
return 0;
}
线性基的交:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=5e4+5;
int n,m;
ll base[35];
struct L_B
{
ll b[35];
int l,r;
L_B()
{
memset(b,0,sizeof(b));
}
inline bool insert(ll x)//向线性基中插入元素
{
for(int i=32;i>=0;--i)
if(x&base[i])
{
if(b[i])
x^=b[i];
else
{
b[i]=x;
return true;
}
}
return false;
}
}tree[maxn<<2];
L_B Merge(L_B A,L_B B)
{
L_B All,C,D;
for(int i=32;i>=0;i--)
{
All.b[i]=A.b[i];
D.b[i]=1ll<<i;
}
for(int i=32;i>=0;i--)
{
if(B.b[i])
{
ll v=B.b[i],k=0;
bool can=1;
for(int j=32;j>=0;j--)
{
if(v&base[j])
{
if(All.b[j])
{
v^=All.b[j];
k^=D.b[j];
}
else
{
can=0;
All.b[j]=v;
D.b[j]=k;
break;
}
}
}
if(can)
{
ll v=0;
for(int j=32;j>=0;j--)
if(k&base[j])
v^=A.b[j];
C.insert(v);
}
}
}
C.l=A.l,C.r=B.r;
return C;
}
void build(int i,int l,int r)
{
tree[i].l=l,tree[i].r=r;
if(l==r)
{
int t1;
ll t2;
scanf("%d",&t1);
while(t1--)
{
scanf("%lld",&t2);
tree[i].insert(t2);
}
return ;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
tree[i]=Merge(tree[i<<1],tree[i<<1|1]);
}
bool query(int i,int l,int r,ll v)
{
if(tree[i].l==l&&tree[i].r==r)
{
for(int j=32;j>=0;j--)
if(v&base[j])
v^=tree[i].b[j];
return v==0?1:0;
}
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid)
return query(i<<1,l,r,v);
else if(l>mid)
return query(i<<1|1,l,r,v);
else
return query(i<<1,l,mid,v)&query(i<<1|1,mid+1,r,v);
}
inline void prework()
{
for(int i=0;i<=32;i++)
base[i]=1ll<<i;
scanf("%d %d",&n,&m);
build(1,1,n);
}
inline void mainwork()
{
int l,r;
ll v;
for(int i=0;i<m;i++)
{
scanf("%d%d%lld",&l,&r,&v);
printf("%s\n",query(1,l,r,v)==1?"YES":"NO");
}
}
int main()
{
prework();
mainwork();
return 0;
}