题目大意:给出一个包含n个元素的数组A以及一个k,接下来进行q次询问,每次询问给出 l 和 r ,要你求出从A[l] , A[l+1] , A[l + 2],...,A[r]中任选出若干个数异或起来的值val,使得 k | val 最大,输出这个最大值。
题目思路:既然是要使得k | val得到的值最大,那么val必然是k这个数上二进制位为0的位置为1的数,同时1的位数要尽可能的多。这样我们就可以先对k取反,求出k二进制位为0的位数变成1的数p,再用A[i]与上p,将这些数放入线性基中。由于每次都是区间查询,我们就可以利用线段树的思想,建立一棵结点为线性基的线段树,每次区间查询的时候就查询出这几个区间合并后的线性基,再用线性基的性质查询最大值即可。复杂度为O(n*logn*logn + q*logn*logn)。
具体实现看代码:
#include
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<= 0; i--) {
if (val & (1ll << i)) {
if (!d[i]) {
d[i] = val; break;
}
val ^= d[i];
}
}
return val > 0;
}
int query() {
int ret = 0;
for (int i = mx - 1; i >= 0; i--) if ((ret ^ d[i]) > ret) ret ^= d[i];
return ret;
}
LB operator+(const LB&_A)const {
LB ret = *this;
for (int i = mx - 1; i >= 0; i--) if (_A.d[i]) ret.add(_A.d[i]);
return ret;
}
} base[MX << 2];
void push_up(int rt) {
base[rt] = base[rt << 1] + base[rt << 1 | 1];
}
void build(int l, int r, int rt) {
base[rt].init();
if (l == r) return;
int m = (l + r) >> 1;
build(lson); build(rson);
push_up(rt);
}
void update(int p, int d, int l, int r, int rt) {
if (l == r) {
base[rt].add(d);
return;
}
int m = (l + r) >> 1;
if (p <= m) update(p, d, lson);
else update(p, d, rson);
push_up(rt);
}
LB query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return base[rt];
int m = (l + r) >> 1;
if (R <= m) return query(L, R, lson);
else if (L > m) return query(L, R, rson);
else return query(L, R, lson) + query(L, R, rson);
}
int main() {
for (scanf("%d", &_); _; _--) {
scanf("%d%d%d", &n, &q, &k);
int val = 0;
for (int i = 30; i >= 0; i--) {
if (!(k & (1 << i))) val |= (1 << i);
}
for (int i = 1; i <= n; i++) {
int x; scanf("%d", &x);
x &= val;
update(i, x, 1, n, 1);
}
while (q--) {
int l, r;
scanf("%d%d", &l, &r);
LB now = query(l, r, 1, n, 1);
int ans = now.query();
ans |= k;
printf("%d\n", ans);
}
}
return 0;
}