最大异或和

题目描述
给定一个非负整数序列 { 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 lpr,使得: 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 12 N , M ≤ 5 N,M \le 5 N,M5
对于测试点 3 − 7 3-7 37 N , M ≤ 80000 N,M \le 80000 N,M80000
对于测试点 8 − 10 8-10 810 N , M ≤ 300000 N,M \le 300000 N,M300000
其中测试点 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 0a[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[p1]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=l1maxr1s[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;
}

你可能感兴趣的:(trie树,可持久化,ACM)