题意:
给出一个长度为 n n n数组, m m m 次操作,操作分为两种:
1. 1. 1. 查询区间 [ l , r ] [l,r] [l,r] 的一些数异或和的最大值。
2. 2. 2. 向数组最后添加一个数 x x x, n = n + 1 n=n+1 n=n+1
题解:
先了解什么是线性基:
线性基就是从一个集合中构造出另一个集合,且满足一下要求
1. 1. 1. 线性基的元素能互相异或得到原集合异或出来的数
2. 2. 2. 线性基满足 1 1 1的条件下,集合元素最少
3. 3. 3. 线性基没有异或和为 0 的子集。
4. 4. 4. 线性基中每个元素的异或方案唯一,也就是说,线性基中不同的异或组合异或出的数都是不一样的。
5. 5. 5. 线性基中每个元素的二进制最高位互不相同。
线性基构造方法:
inline void insert(long long x) {
for (int i = 55; i + 1; i--) {
if (!(x >> i)) // x的第i位是0
continue;
if (!p[i]) {
p[i] = x;
break;
}
x ^= p[i];
}
}
再来看这道题:
设 d p [ i ] [ j ] dp[i][j] dp[i][j]表示前 i 个数的线性基, p o s [ i ] [ j ] pos[i][j] pos[i][j] 表示前 i 个数的线性基 j j j 位的位置
那么在插入新的数 X X X 时,若 d p [ i ] [ j ] dp[i][j] dp[i][j] 有值,且 i > p o s [ i ] [ j ] i>pos[i][j] i>pos[i][j] ,那么就把 X X X 与 d p [ i ] [ [ j ] dp[i][[j] dp[i][[j]交换 ,保证 线性基里的数都是尽量向右靠的。那么在查询的过程中,只需判断位置是否 ≥ l \geq l ≥l 即可。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=5e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int a[MAXN];
int dp[MAXN][31];
int pos[MAXN][31];
void add(int id,int x){
int temp=id;
for(int i=0;i<=30;i++){
dp[id][i]=dp[id-1][i];
pos[id][i]=pos[id-1][i];
}
for(int i=30;i>=0;i--){
if((x>>i)&1){
if(!dp[id][i]){
dp[id][i]=x;
pos[id][i]=temp;
break;
}
else{
if(temp>pos[id][i]){
swap(x,dp[id][i]);
swap(temp,pos[id][i]);
}
x=(x^dp[id][i]);
}
}
}
}
int solve(int l,int r){
int ans=0;
for(int i=30;i>=0;i--){
if(pos[r][i]>=l){
if((ans^dp[r][i])>ans){
ans=(ans^dp[r][i]);
}
}
}
return ans;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
for(int i=0;i<=30;i++){
dp[0][i]=pos[0][i]=0;
}
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
cin>>a[i];
add(i,a[i]);
}
int ans=0;
while(m--){
int op;
scanf("%d",&op);
if(op==0){
int l,r;
scanf("%d%d",&l,&r);
l=(l^ans)%n+1;
r=(r^ans)%n+1;
if(l>r) swap(l,r);
ans=solve(l,r);
printf("%d\n",ans);
}
else{
int x;
scanf("%d",&x);
x=x^ans;
n++;
add(n,x);
}
}
}
}