【LG4735】最大异或和

【LG4735】最大异或和

题意

洛谷

题解

维护一个前缀异或和\(S_i\)

对于一个询问操作\(l\)\(r\)\(x\)

就是等价于求一个位置\(p\)(\(l\leq p \leq r)\)使得\(S_nxorS_{p-1}xorx\)最大

可将此问题转化为求\(p\)使\(S_{p-1}\) \(xor\) \(S_n xor x\)最大

先将后半部分求出然后在可持久化\(trie\)上贪心即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring> 
#include<cmath> 
#include<algorithm>
using namespace std;
inline int gi() {
	register int data = 0, w = 1;
	register char ch = 0;
	while (!isdigit(ch) && ch != '-') ch = getchar(); 
	if (ch == '-') w = -1, ch = getchar();
	while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
	return w * data; 
}
const int MAX_N = 600005; 
struct Trie {int ch[2], latest; } t[MAX_N * 24]; 
int s[MAX_N], rt[MAX_N], N, M, tot;
void insert(int i, int k, int p, int q) { 
	if (k < 0) return (void)(t[q].latest = i);
	int c = s[i] >> k & 1; 
	if (p) t[q].ch[c ^ 1] = t[p].ch[c ^ 1]; 
	t[q].ch[c] = ++tot;
	insert(i, k - 1, t[p].ch[c], t[q].ch[c]);
	t[q].latest = max(t[t[q].ch[0]].latest, t[t[q].ch[1]].latest); 
}
int query(int o, int val, int k, int limit) { 
	if (k < 0) return s[t[o].latest] ^ val; 
	int c = val >> k & 1; 
	if (t[t[o].ch[c ^ 1]].latest >= limit) return query(t[o].ch[c ^ 1], val, k - 1, limit);
	else return query(t[o].ch[c], val, k - 1, limit); 
} 

int main () { 
	N = gi(), M = gi(); 
	t[0].latest = -1; 
	rt[0] = ++tot; 
	insert(0, 23, 0, rt[0]);
	for (int i = 1; i <= N; i++) {
		int x = gi();
		s[i] = s[i - 1] ^ x; 
		rt[i] = ++tot; 
		insert(i, 23, rt[i - 1], rt[i]); 
	} 
	for (int i = 1; i <= M; i++) { 
		char ch[5]; scanf("%s", ch);
		if (ch[0] == 'A') { 
			int x = gi(); 
            rt[++N] = ++tot; 
			s[N] = s[N - 1] ^ x;
			insert(N, 23, rt[N - 1], rt[N]);
		} else {
			int l = gi(), r = gi(), x = gi();
			printf("%d\n", query(rt[r - 1], x ^ s[N], 23, l - 1)); 
		} 
	} 
	return 0; 
} 
posted @ 2018-12-20 21:55  heyujun  阅读(229)  评论(0编辑  收藏  举报