【BZOJ3261】最大异或和【可持久化Trie树】

Trie维护序列前缀异或和,然后贪心找就可以啦。

#include <cstdio>

const int maxn = 600005, maxd = 26, maxnode = maxn * maxd;

int n, m, bin[maxd], num[maxn], son[maxnode][2], sum[maxnode], root[maxn], triecnt;

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

inline void insert(int &pos, int c) {
	int now = ++triecnt, last = pos; pos = now;
	for(int i = maxd - 1; i >= 0; i--) {
		son[now][0] = son[last][0]; son[now][1] = son[last][1];
		sum[now] = sum[last] + 1;
		bool ind = c & bin[i];
		last = son[last][ind];
		now = son[now][ind] = ++triecnt;
	}
	sum[now] = sum[last] + 1;
}

inline int query(int l, int r, int c) {
	int ans = 0;
	for(int i = maxd - 1; i >= 0; i--) {
		bool ind = c & bin[i];
		if(sum[son[r][ind ^ 1]] - sum[son[l][ind ^ 1]])
			ans += bin[i], l = son[l][ind ^ 1], r = son[r][ind ^ 1];
		else l = son[l][ind], r = son[r][ind];
	}
	return ans;
}		

int main() {
	freopen("xor.in", "r", stdin); freopen("xor.out", "w", stdout);

	bin[0] = 1; for(int i = 1; i < maxd; i++) bin[i] = bin[i - 1] << 1;

	n = iread(); m = iread(); num[1] = 0; ++n;
	for(int i = 2; i <= n; i++) num[i] = iread() ^ num[i - 1];

	for(int i = 1; i <= n; i++) insert(root[i] = root[i - 1], num[i]);
	
	while(m--) {
		char ch = getchar(); for(; ch != 'A' && ch != 'Q'; ch = getchar());
		if(ch == 'A') {
			++n; num[n] = iread() ^ num[n - 1];
			insert(root[n] = root[n - 1], num[n]);
		} else {
			int l = iread(), r = iread(), c = iread();
			printf("%d\n", query(root[l - 1], root[r], c ^ num[n]));
		}
	}
	return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/BraketBN/article/details/50756429
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞