专题:可持久化数据结构
作者:互联网
目录
最大异或和
题意:
给定一个非负整数序列 a,初始长度为 N。
有 M 个操作,有以下两种操作类型:
A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N 增大 1。
Q l r x:询问操作,你需要找到一个位置 p,满足 l≤p≤r,使得:a[p] xor a[p+1] xor … xor a[N] xor x 最大,输出这个最大值。
题解:转化为求区间[l-1,r-1]内的s[i]和(s[n]^x)进行异或的最大值
构建可持久化01Trie
如果区间是[1,n],直接在普通的trie上贪心选择即可
如果没有区间左端点的限制,只需要在第r-1个版本的trie上贪心选择即可
对于限制[l-1,r-1],可以记录每个结点的两个子结点中较晚出现的版本号max_id,只需要在第r-1个版本的trie上贪心时保证走向结点的max_id>=l-1即可。
max_id可以在递归insert时自下而上求出来。
//
// Created by vv123 on 2022/9/9.
//
#include <bits/stdc++.h>
using namespace std;
const int N = 6e5 + 10, M = N * 25;
int n, m, s[N];
int tr[M][2], max_id[M], root[N], idx;
void insert(int i, int k, int pre, int now) {
if (k < 0) {
max_id[now] = i;
return;
}
int v = s[i] >> k & 1;
if (pre) tr[now][v ^ 1] = tr[pre][v ^ 1];
tr[now][v] = ++idx;
insert(i, k - 1, tr[pre][v], tr[now][v]);
max_id[now] = max(max_id[tr[now][0]], max_id[tr[now][1]]);
}
int query(int root, int C, int L) {
int p = root;
for (int i = 23; i >= 0; i--) {
int v = C >> i & 1;
if (max_id[tr[p][v ^ 1]] >= L) p = tr[p][v ^ 1];
else p = tr[p][v];
}
return C ^ s[max_id[p]];
}
int main() {
cin >> n >> m;
max_id[0] = -1;
root[0] = ++idx;
insert(0, 23, 0, root[0]);
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
s[i] = s[i - 1] ^ x;
root[i] = ++idx;
insert(i, 23, root[i - 1], root[i]);
}
while (m--) {
string op; int l, r, x;
cin >> op;
if (op == "A") {
cin >> x;
n++;
s[n] = s[n - 1] ^ x;
root[n] = ++idx;
insert(n, 23, root[n - 1], root[n]);
} else {
cin >> l >> r >> x;
cout << query(root[r - 1], s[n] ^ x, l - 1) << "\n";
}
}
return 0;
}
未完待续
标签:now,专题,持久,int,max,tr,数据结构,root,id 来源: https://www.cnblogs.com/vv123/p/16673619.html