http://acm.hdu.edu.cn/showproblem.php?pid=6579
题意:
n<5e5,q<5e5
思路:
维护每一位前缀线性基。维护线性基的每一位的对应的下标。
第i位线性基向第i+1位递推时,需要i+1位的线性基继承第i位之后,用a[i+1]更新i+1的线性基,线性基的每一位尽量的维护右边的数。
查询的时候,查询r的前缀线性基,满足在l左边的贪心更新答案。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define FI first
#define SE second
#define MP make_pair
#define PII pair<int,int>
const int mod = 1e9+7;
const int MX = 1e6+5;
const int LOG = 30;
int a[MX],b[MX][LOG+5],p[MX][LOG+5];
void insertx(int pos,int x,int now){ //插入
for(int i=LOG;i>=0;i--){
if(x>>i&1){
if(!b[now][i]){//必须填充
b[now][i]=x;
p[now][i]=pos;
return;
}
else {//可以向右替换
if(pos>p[now][i]) swap(pos,p[now][i]),swap(x,b[now][i]);
}
x^=b[now][i];
}
}
return ;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("C:\\Users\\RSHS\\Desktop\\in.txt", "r", stdin);
freopen("C:\\Users\\RSHS\\Desktop\\out.txt", "w", stdout);
#endif
int T;cin>>T;while(T--){
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
for(int j=0;j<=LOG;j++) b[i][j]=b[i-1][j],p[i][j]=p[i-1][j];//继承i-1的前缀
insertx(i,a[i],i);//第i位更新,所有b尽量向右
}
int lastans=0;
while(m--){
int op;scanf("%d",&op);
if(op==0){
int l,r;scanf("%d%d",&l,&r);
l=(l^lastans)%(n)+1,r=(r^lastans)%(n)+1;
if(l>r)swap(l,r);
int res=0;
for(int i=LOG;i>=0;i--){
if(p[r][i]>=l)
res=max(res,res^b[r][i]);
}
lastans=res;
printf("%d\n",res);
}
if(op==1){
n=n+1;
int x;scanf("%d",&x);x^=lastans;
for(int j=0;j<=LOG;j++) b[n][j]=b[n-1][j],p[n][j]=p[n-1][j];//继承i-1的前缀
insertx(n,x,n);//第i位更新,所有b尽量向右
}
}
}
return 0;
}