原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=6579
题意:给出一个数组,有两种操作,一种是在数组后面添一个数,一个数区间查询异或最大值。
此题原题CF1100F
不同的是CF那题没有添加操作,也没有强制在线而已.
思路:由于这个题区间查询用线段树的话时间复杂度不正确,所以要对线性基多做一点处理。
定义
p
o
s
[
]
pos[]
pos[]数组表示在线性基中第j位为1的数字在原数组的下标。
那么我们对
n
n
n个数的每个前缀搞个线性基,同时记录线性基的
p
o
s
pos
pos。
那么假如查询区间
[
l
,
r
]
[l,r]
[l,r]的区间异或最大值,我们直接取出区间
[
1
,
r
]
[1,r]
[1,r]对应的线性基,然后查询这个线性基可以组成的最大值,不过要加一个判断条件,也就是如果线性基的第
i
i
i位是
1
1
1,那么如果
p
o
s
[
i
]
<
l
pos[i]<l
pos[i]<l,答案是不会取这个值的,因为
p
o
s
[
i
]
<
l
pos[i]<l
pos[i]<l就说明了在
[
1
,
r
]
[1,r]
[1,r]区间上,第
i
i
i位是
1
1
1的那个数出现在
l
l
l之前,所以当你查询
[
l
,
r
]
[l,r]
[l,r]的时候,是没有这个数字的。
这个题目要改变一下 i n s e r t insert insert函数的写法,把 p o s pos pos写进去。
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
//typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
const int MAXL = 31;
const int M = 5e5 + 5;
int a[maxn][MAXL + 1];//前缀线性基
int pos[M][MAXL + 1];//记录第i位是1是哪个元素
void Insert(int id, int t, int p) {//下面写法的改变
for (int j = MAXL; j >= 0; j--) {
if (!(t & (1 << j))) continue;
if (!a[j]) {
a[id][j] = t;
pos[id][j] = p;
break;
}
if (pos[id][j] < p) {
swap(pos[id][j], p);
swap(a[id][j], t);
}
t ^= a[id][j];
}
}
int x;
int l, r;
int T, n, m;
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &x);
for (int j = MAXL; j >= 0; j--) {
pos[i][j] = pos[i - 1][j];
a[i][j] = a[i - 1][j];
}
Insert(i, x, i);
}
int lastans = 0;
while (m--) {
int op;
scanf("%d", &op);
if (op == 1) {
scanf("%d", &x);
x ^= lastans;
n++;
for (int j = MAXL; j >= 0; j--) {
pos[n][j] = pos[n - 1][j];
a[n][j] = a[n - 1][j];
}
Insert(n, x, n);
} else {
scanf("%d%d", &l, &r);
l = (l ^ lastans) % n + 1;
r = (r ^ lastans) % n + 1;
if (l > r) {
swap(l, r);
}
int num = 0;
for (int j = MAXL; j >= 0; j--) {
if (pos[r][j] < l) continue;
if ((num ^ a[r][j]) > num) num ^= a[r][j];
}
printf("%d\n", num);
lastans = num;
}
}
}
return 0;
}