ACM-ICPC 2017 西安 A. XOR(线段树思想合并线性基)

题目大意:给出一个包含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;
}

 

你可能感兴趣的:(数论,数据结构,ACM,线性基)