Luogu P4735 最大异或和

可持久化\(01Trie\)。感觉不是很会写,改天复习完主席树会再来学一次。

#include <bits/stdc++.h>
using namespace std;

const int N = 600010;
int s[N], rt[N], cnt[N * 25];
int max_size = 1, ch[N * 25][2];

void ins (int now, int pre, int x) {
	for (int t = 25; t >= 0; --t) {
		int i = (x >> t) & 1;
		ch[now][!i] = ch[pre][!i]; //不修改的 -> 直接连起来
		ch[now][i] = ++max_size; //修改的 -> 新建节点
		cnt[ch[now][i]] = cnt[ch[pre][i]] + 1; //维护一个数的个数
		now = ch[now][i], pre = ch[pre][i];
	}
	//只有在存在新节点的部分,cnt[now] 才会大于 cnt[pre]
}

int qry (int l, int r, int x) {
	int ans = 0;
	for (int t = 25; t >= 0; --t) {
		int i = (x >> t) & 1;
		if (cnt[ch[r][!i]] > cnt[ch[l][!i]]) {
			ans += (1 << t);
			l = ch[l][!i];
			r = ch[r][!i];
		} else {
			l = ch[l][i];
			r = ch[r][i];
	    }
		//限制其不能向版本更低的地方走
		//至少添加一个数, 不在i上就在!i上,不允许向cnt更低的地方走
	}
	return ans;
}


int n, m, x, l, r; char opt;

int main () {
	cin >> n >> m;
    rt[0] = ++max_size;
    ins (rt[0], 0, 0);
    for (int i = 1; i <= n; ++i) {
        scanf ("%d", &s[i]);
        s[i] ^= s[i - 1];
        rt[i] = ++max_size;
        ins (rt[i], rt[i - 1], s[i]);
    }
    for (int i = 1; i <= m; ++i) {
        scanf (" %c", &opt);
        if (opt == 'A') {
            scanf ("%d", &x);
			n = n + 1;
            s[n] = s[n - 1] ^ x;
            rt[n] = ++max_size;
            ins (rt[n], rt[n - 1], s[n]);
        } else {
            scanf ("%d %d %d", &l, &r, &x); --l, --r;
            if(l <= 0) {
				printf ("%d\n", qry (0, rt[r], x ^ s[n]));
			} else {
				printf ("%d\n", qry (rt[l - 1], rt[r], x ^ s[n]));
			}
		}
    }
    return 0;
}

posted @ 2019-02-27 17:41  maomao9173  阅读(109)  评论(0编辑  收藏  举报