BZOJ3261: 最大异或和(可持久化trie树)

题意

题目链接

Sol

\(sum[i]\)表示\(1 - i\)的异或和

首先把每个询问的\(x \oplus sum[n]\)就变成了询问前缀最大值

可持久化Trie树维护前缀xor,建树的时候维护一下每个节点被遍历了多少次

注意设置好偏移量,不然询问区间为\([1, 1]\)的时候可能挂掉

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 6e5 + 10;
inline int read() {
	char c = getchar(); int x = 0, f = 1;
	while(c < '0' || c > '9') {if(c == '-')f =- 1; c = getchar();}
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
int N, M, a[MAXN], sum[MAXN], cnt[MAXN * 25], ch[MAXN * 25][2], tot, root[MAXN];
void insert(int i, int x) {
	x = (sum[i] = sum[i - 1] ^ x);
	int p = root[i - 1], now = (root[i] = ++tot);
	for(int i = 23; i >= 0; i--) {
		bool nxt = x >> i & 1;
		ch[now][nxt ^ 1] = ch[p][nxt ^ 1];
		now = ch[now][nxt] = ++tot; p = ch[p][nxt];
		cnt[now] = cnt[p] + 1;
	}
}
int Query(int l, int r, int x) {
	r = root[r], l = root[l];
	int ans = 0;
	for(int i = 23; i >= 0; i--) {
		int nxt = x >> i & 1;
		if(cnt[ch[r][nxt ^ 1]] - cnt[ch[l][nxt ^ 1]] > 0) ans += 1 << i, r = ch[r][nxt ^ 1], l = ch[l][nxt ^ 1];
		else r = ch[r][nxt], l = ch[l][nxt];
	}
	return ans;
}
int main() {
	N = read(); M = read();
	for(int i = 1; i <= N; i++) a[i] = read(), insert(i, a[i]);
	char ss[4];
	for(int i = 1; i <= M; i++) {
		scanf("%s", ss + 1);
		if(ss[1] == 'A') 
			N++, a[N] = read(), insert(N, a[N]);
		else {
			int l = read() - 1, r = read() - 1, val = read();
			printf("%d\n", Query(l - 1, r, val ^ sum[N]));
		}
	}
}
/*
5 5
2 6 4 3 6
A 1 
Q 3 5 4 
A 4 
Q 5 7 0 
Q 3 6 6 
*/
posted @ 2018-09-30 21:56  自为风月马前卒  阅读(282)  评论(0编辑  收藏  举报

Contact with me