题目链接http://acm.hdu.edu.cn/showproblem.php?pid=6579
题意
两个操作,一是询问区间内子序列异或最大值,二是在末尾添加一个值。
题解
线性基知识
利用线性基可以维护子序列最大值。做一个前缀的线性基,线性基里记录第i位最靠右边的值。对于每个查询,判断该值的位置是否>=l。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+7;
int a[50],aa[N][50],b[50],bb[N][50];
bool add(int p,int v){
int pp=p;
for(int i=30;i>=0;i--){
if(v&(1<<i)){
if(!a[i]){
a[i]=v;
b[i]=pp;
break;
}
if(b[i]<pp){
swap(b[i],pp);
swap(a[i],v);
}
v^=a[i];
}
}
for(int i=30;i>=0;i--){
aa[p][i]=a[i];
bb[p][i]=b[i];
}
}
int que(int l,int r){
int ret=0;
for(int i=30;i>=0;i--){
if(bb[r][i]>=l&&(ret^aa[r][i])>ret){
ret^=aa[r][i];
}
}
return ret;
}
int main(){
int t,n,m;
scanf("%d",&t);
while(t--){
int lst=0;
scanf("%d%d",&n,&m);
for(int i=30;i>=0;i--) a[i]=b[i]=0;
for(int i=1,x;i<=n;i++){
scanf("%d",&x);
add(i,x);
}
for(int i=1,o,l,r;i<=m;i++){
scanf("%d",&o);
if(o){
scanf("%d",&r);
r^=lst;
add(++n,r);
}
else{
scanf("%d%d",&l,&r);
l=(l^lst)%n+1,r=(r^lst)%n+1;
if(l>r) swap(l,r);
printf("%d\n",lst=que(l,r));
}
}
}
}