Problem Description
There is an integer sequence aa of length nn and there are two kinds of operations:
- 0 l r: select some numbers from al...ar so that their xor sum is maximum, and print the maximum value.
- 1 x: append x to the end of the sequence and let n=n+1.
Input
There are multiple test cases. The first line of input contains an integer T(T≤10), indicating the number of test cases.
For each test case:
The first line contains two integers n,m(1≤n≤5×105,1≤m≤5×105), the number of integers initially in the sequence and the number of operations.
The second line contains nn integers a1,a2,...,an(0≤ai<230), denoting the initial sequence.
Each of the next mm lines contains one of the operations given above.
It's guaranteed that ∑n≤106,∑m≤106,0≤x<230.
And operations will be encrypted. You need to decode the operations as follows, where lastans denotes the answer to the last type 0 operation and is initially zero:
For every type 0 operation, let l=(l xor lastans)mod n + 1, r=(r xor lastans)mod n + 1, and then swap(l, r) if l>r.
For every type 1 operation, let x=x xor lastans.Output
For each type 0 operation, please output the maximum xor sum in a single line.
Sample Input
1
3 3
0 1 2
0 1 1
1 3
0 3 4Sample Output
1
3
题意:t 组数据,每组给出一个长度为 n 的序列和 m 组查询,每组查询分为 2 种操作,1 x 代表将数 x 追加到序列中,0 l r 代表查询区间 [l,r] 中的最大异或和,每次给出的查询要求异或上一次的结果,强制在线
思路:
根据查询最大异或和可以想到利用线性基来做,但线性基是用来查询整个序列的最大异或和,本题仅涉及到求区间 [l,r] 的最大异或和,就需要用前缀线性基来做。
Source Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<unordered_map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL quickModPow(LL a,LL b,LL mod){ LL res=1; a=a%mod; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1;} return res; }
LL getInv(LL a,LL mod){ return quickModPow(a,mod-2,mod); }
LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); }
LL LCM(LL x,LL y){ return x/GCD(x,y)*y; }
const double EPS = 1E-10;
const int MOD = 1E9+7;
const int N = 500000+5;
const int dx[] = {-1,1,0,0,1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;
struct PrefixLinearBasis{
int d[N][32];//前缀线性基
int pos[N][32];//最后一个修改i这个位置的数
int num;
PrefixLinearBasis(){
memset(d,0,sizeof(d));
memset(pos,0,sizeof(pos));
num=0;
}
void add(int x){//向线性基中添加x
num++;
for(int i=0; i<32; i++){//复制前num-1个线性基
d[num][i]=d[num-1][i];
pos[num][i]=pos[num-1][i];
}
int P=num;
for(int i=31; i>=0; i--){
if((x>>i)&1){
if(d[num][i]){//插入失败
if(pos[num][i]<P){//交换位置
swap(pos[num][i], P);
swap(d[num][i],x);
}
x^=d[num][i];//异或
}
else{//插入成功
d[num][i]=x;
pos[num][i]=P;
break;
}
}
}
}
int queryMax(int l,int r){//查询[l,r]中的最大值
int res=0;
for (int i=31; i>=0; i--){
if(pos[r][i]<l)
continue;
if ((res^d[r][i])>res)
res^=d[r][i];
}
return res;
}
int queryMin(int l,int r) {//查询[l,r]中的最小值
for(int i=0; i<=60; i++){
if(pos[r][i]<l)
continue;
if(d[r][i])
return d[r][i];
}
return 0;
}
}PLB;
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(PLB.d[0], 0, sizeof(PLB.d[0]));
memset(PLB.pos[0], 0, sizeof(PLB.pos[0]));
PLB.num=0;
int n,m;
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++){
int x;
scanf("%d",&x);
PLB.add(x);
}
int ans=0;
for(int i=1; i<=m; i++){
int op=0;
scanf("%d",&op);
if (op==0){
int x = 0, y = 0;
scanf("%d%d", &x, &y);
x = (x ^ ans) % PLB.num + 1;
y = (y ^ ans) % PLB.num + 1;
if (x > y)
swap(x, y);
ans = PLB.queryMax(x, y);
printf("%d\n", ans);
}
else if(op==1){
int x;
scanf("%d",&x);
x^=ans;
PLB.add(x);
}
}
}
return 0;
}