题目描述
给定一个非负整数序列 { a } \{a\} {a},初始长度为 n n n。
有 m m m 个操作,有以下两种操作类型:
A x
:添加操作,表示在序列末尾添加一个数 x x x,序列的长度 n + 1 n+1 n+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
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 − 2 1-2 1−2, N , M ≤ 5 N,M \le 5 N,M≤5。
对于测试点 3 − 7 3-7 3−7, N , M ≤ 80000 N,M \le 80000 N,M≤80000。
对于测试点 8 − 10 8-10 8−10, N , M ≤ 300000 N,M \le 300000 N,M≤300000。
其中测试点 1 , 3 , 5 , 7 , 9 1, 3, 5, 7, 9 1,3,5,7,9 保证没有修改操作。
0 ≤ a [ i ] ≤ 1 0 7 0 \le a[i] \le 10^7 0≤a[i]≤107。
设 s [ i ] s[i] s[i]表示序列 a a a的前 i i i个数 ⊕ \oplus ⊕得到的结果,则
a [ p ] ⊕ a [ p + 1 ] ⊕ . . . ⊕ a [ N ] ⊕ x = s [ p − 1 ] ⊕ s [ N ] ⊕ x a[p] \oplus a[p+1] \oplus ... \oplus a[N] \oplus x=s[p-1]\oplus s[N]\oplus x a[p]⊕a[p+1]⊕...⊕a[N]⊕x=s[p−1]⊕s[N]⊕x
因此问题转化成求 max i = l − 1 r − 1 s [ i ] ⊕ s [ N ] ⊕ x \max\limits_{i=l-1}^{r-1}s[i]\oplus s[N] \oplus x i=l−1maxr−1s[i]⊕s[N]⊕x。
使用可持久化 T r i e Trie Trie维护即可。
注意讨论 l = 1 l=1 l=1和 r = 1 r=1 r=1的情况。
#include
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scanf("%c",&a)
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector
#define pii pair
#define mii unordered_map
#define msi unordered_map
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;
inline int qr() {
int f = 0, fu = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')fu = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
f = (f << 3) + (f << 1) + c - 48;
c = getchar();
}
return f * fu;
}
const int N = 6e5 + 10, H = 23;
struct Trie {
int ch[N * H][2];
int rt[N], tot;
int cnt[N * H];
inline int insert(int p, int x) {
int np = ++tot, nr = tot;
repd(i, H, 0) {
cnt[np] = cnt[p] + 1;
if ((x >> i) & 1) {
if (!ch[np][1])ch[np][1] = ++tot;
ch[np][0] = ch[p][0];
np = ch[np][1];
p = ch[p][1];
} else {
if (!ch[np][0])ch[np][0] = ++tot;
ch[np][1] = ch[p][1];
np = ch[np][0];
p = ch[p][0];
}
}
cnt[np] = cnt[p] + 1;
return nr;
}
inline int ask(int p1, int p2, int x) {
int res = 0;
repd(i, H, 0) {
int id = (x >> i) & 1;
if (cnt[ch[p2][!id]] - cnt[ch[p1][!id]])
res += 1 << i, p1 = ch[p1][!id], p2 = ch[p2][!id];
else p1 = ch[p1][id], p2 = ch[p2][id];
}
return res;
}
} tr;
int a[N], n, m;
char op;
int main() {
n = qr(), m = qr();
repi(i, 1, n)a[i] = a[i - 1] ^ qr(), tr.rt[i] = tr.insert(tr.rt[i - 1], a[i]);
while (m--) {
cin >> op;
if (op == 'A')n++, a[n] = qr() ^ a[n - 1], tr.rt[n] = tr.insert(tr.rt[n - 1], a[n]);
else {
int l = qr() - 1, r = qr() - 1, x = qr();
pi(l == r && l == 0 ? a[n] ^ x : tr.ask(tr.rt[max(l - 1, 0)], tr.rt[r], a[n] ^ x));
}
}
return 0;
}