线性基 求区间异或和最大值
线性基 求区间异或和最大值
http://acm.hdu.edu.cn/showproblem.php?pid=6579
对于ii我们记录[1,i][1,i]每个基底最靠近ii的位置和这个位置的值,然后查询时看rr这个位置记录的每个基底的位置是否大于等于ll,如果大于等于那么[l,r][l,r]内一定有一个位置可以贡献这个基底,然后比较答案大小即可。
本题和https://codeforces.com/contest/1100/problem/F一样的写法只是多了个操作而已。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int d[32],pos[32], base[500005][32], las[500005][32];
int a[500005];
void add(int x,int pp){
for(int i=30;i>=0;i--){
if( x& ((1ll)<<i )){
if(pos[i] < pp) {
swap(d[i], x);
swap(pos[i], pp);
}
if(d[i]){
x=x^d[i];
}
else{
d[i]=x;
pos[i]=pp;
break;
}
}
}
}
int main(){
int t;
cin >> t;
int n,m;
int op,l,r,ans;
while(t--){
cin >> n >> m;
for(int i=0;i<32;i++){
d[i]=0;
pos[i]=0;
}
for(int i=0;i<n;i++){
scanf("%d",a+i);
add(a[i],i+1);
for(int j = 30; j >= 0; --j) base[i+1][j] = d[j], las[i+1][j] = pos[j];
}
int lastans = 0;
while(m--){
scanf("%d",&op);
if(op){
scanf("%d",&op);
op^=lastans;
n++;
add(op,n);
for(int i = 30; i >= 0; --i) base[n][i] = d[i], las[n][i] = pos[i];
}
else{
scanf("%d%d",&l,&r);
l = (l^lastans)%n+1;
r = (r^lastans)%n+1;
if(l>r){
swap(l,r);
}
// ans=0;
lastans=0;
for(int i = 30; i >= 0; --i) {
if(las[r][i] >= l && (lastans ^ base[r][i]) > lastans) {
lastans ^= base[r][i];
}
}
// lastans=ans;
cout << lastans <<endl;
}
}
}
}