P4735 最大异或和 题解
P4735 最大异或和
题面:
题目描述
给定一个非负整数序列 { a } \{a\} {a},初始长度为 N N N。
有 M M M 个操作,有以下两种操作类型:
A x
:添加操作,表示在序列末尾添加一个数 x x x,序列的长度 N N N 加 1 1 1。Q l r x
:询问操作,你需要找到一个位置 p p p,满足 l ≤ p ≤ r l \le p \le r l≤p≤r,使得: a [ p ] ⊕ a [ p + 1 ] ⊕ . . . ⊕ a [ N ] ⊕ x a[p] \oplus a[p+1] \oplus ... \oplus a[N] \oplus x a[p]⊕a[p+1]⊕...⊕a[N]⊕x 最大,输出最大值。输入格式
第一行包含两个整数 N , M N, M N,M,含义如问题描述所示。
第二行包含 N N N 个非负整数,表示初始的序列 A A A。
接下来 M M M 行,每行描述一个操作,格式如题面所述。输出格式
假设询问操作有 T T T 个,则输出应该有 T T T 行,每行一个整数表示询问的答案。
样例 #1
样例输入 #1
5 5 2 6 4 3 6 A 1 Q 3 5 4 A 4 Q 5 7 0 Q 3 6 6
样例输出 #1
4 5 6
提示
- 对于所有测试点, 1 ≤ N , M ≤ 3 × 1 0 5 1\le N,M \le 3\times 10 ^ 5 1≤N,M≤3×105, 0 ≤ a i ≤ 1 0 7 0\leq a_i\leq 10 ^ 7 0≤ai≤107。
首先,动态加数?平衡 trie?
显然不可做。
我们得考虑异或的性质——自反性!
转换一下题面: a [ p ] ⊕ a [ p + 1 ] ⊕ … ⊕ a [ N ] = ( ⊕ i = 1 N a [ i ] ) ⊕ ( ⊕ i = 1 p − 1 a [ i ] ) a[p] \oplus a[p+1] \oplus \ldots \oplus a[N] = (\oplus_{i = 1}^N a[i]) \oplus (\oplus_{i = 1}^{p - 1} a[i]) a[p]⊕a[p+1]⊕…⊕a[N]=(⊕i=1Na[i])⊕(⊕i=1p−1a[i])
( ⊕ i = 1 N a [ i ] ) (\oplus_{i = 1}^N a[i]) (⊕i=1Na[i]),我们用一个全局tag就可以搞定。
( ⊕ i = 1 p − 1 a [ i ] ) (\oplus_{i = 1}^{p - 1} a[i]) (⊕i=1p−1a[i]),我们用 trie 来做定位。
其中 l ≤ p ≤ r l \leq p \leq r l≤p≤r,我们用 可持久化01-trie + 01-trie上二分 就可以解决!
AC-code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int rd() {int x = 0, w = 1;char ch = 0;while (ch < '0' || ch > '9') {if (ch == '-') w = -1;ch = getchar();}while (ch >= '0' && ch <= '9') {x = x * 10 + (ch - '0');ch = getchar();}return x * w;
}
void wt(int x) {static int sta[35];int f = 1;if(x < 0) f = -1,x *= f;int top = 0;do {sta[top++] = x % 10, x /= 10;} while (x);if(f == -1) putchar('-');while (top) putchar(sta[--top] + 48);
}
const int N = 3e5+5;
int rt[N << 2],n,m,a[N<<2];
namespace zo_trie{
int siz[N * 50],ls[N * 50],rs[N * 50],cnt;int update(int pr,int x,int dep) {int re = ++cnt;siz[re] = siz[pr] + 1;ls[re] = ls[pr];rs[re] = rs[pr];if(dep < 0) return re;((x >> dep) & 1) ? rs[re] = update(rs[pr],x,dep - 1) : ls[re] = update(ls[pr],x,dep - 1);return re;
}int query(int x,int y,int k,int dep){if(dep < 0) return 0;int lsz = siz[ls[y]] - siz[ls[x]];int rsz = siz[rs[y]] - siz[rs[x]];if((k >> dep) & 1) {if(lsz) return (int)(1<<(int)dep) + query(ls[x],ls[y],k,dep - 1);else return query(rs[x],rs[y],k,dep - 1);}else {if(rsz)return (int)(1<<(int)dep) + query(rs[x],rs[y],k,dep - 1);else return query(ls[x],ls[y],k,dep - 1);}
}}signed main() {n = rd(),m = rd();for(int i = 1;i<=n;i++) a[i] = rd();for(int i = 1;i<=n;i++) a[i] ^= a[i - 1];rt[0] = zo_trie::update(rt[0],0,25);for(int i = 1;i<=n;i++) rt[i] = zo_trie::update(rt[i - 1],a[i],25);while(m--) {char opt = getchar();while(opt != 'A' && opt != 'Q') opt = getchar();int A,B,C;switch(opt) {case 'A':A = rd();n++;a[n] = a[n - 1] ^ A;rt[n] = zo_trie::update(rt[n - 1],a[n],25);break;case 'Q':A = rd(),B = rd(),C = rd();A--,B--;C ^= a[n];if(A > 0) wt(zo_trie::query(rt[A - 1],rt[B],C,25));else wt(zo_trie::query(0,rt[B],C,25));putchar('\n');break;default:puts("Error");exit(0);break;}}return 0;
}