1. 程式人生 > >【LG4735】最大異或和

【LG4735】最大異或和

【LG4735】最大異或和

題意

洛谷

題解

維護一個字首異或和\(S_i\)
對於一個詢問操作\(l\)\(r\)\(x\)
就是等價於求一個位置\(p\)(\(l\leq p \leq r)\)使得\(S_nxorS_{p-1}xorx\)最大
可將此問題轉化為求\(p\)使\(S_{p-1}\) \(xor\) \(S_n xor x\)最大
先將後半部分求出然後在可持久化\(trie\)上貪心即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring> 
#include<cmath> 
#include<algorithm>
using namespace std;
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar();
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
    return w * data; 
}
const int MAX_N = 600005; 
struct Trie {int ch[2], latest; } t[MAX_N * 24]; 
int s[MAX_N], rt[MAX_N], N, M, tot;
void insert(int i, int k, int p, int q) { 
    if (k < 0) return (void)(t[q].latest = i);
    int c = s[i] >> k & 1; 
    if (p) t[q].ch[c ^ 1] = t[p].ch[c ^ 1]; 
    t[q].ch[c] = ++tot;
    insert(i, k - 1, t[p].ch[c], t[q].ch[c]);
    t[q].latest = max(t[t[q].ch[0]].latest, t[t[q].ch[1]].latest); 
}
int query(int o, int val, int k, int limit) { 
    if (k < 0) return s[t[o].latest] ^ val; 
    int c = val >> k & 1; 
    if (t[t[o].ch[c ^ 1]].latest >= limit) return query(t[o].ch[c ^ 1], val, k - 1, limit);
    else return query(t[o].ch[c], val, k - 1, limit); 
} 

int main () { 
    N = gi(), M = gi(); 
    t[0].latest = -1; 
    rt[0] = ++tot; 
    insert(0, 23, 0, rt[0]);
    for (int i = 1; i <= N; i++) {
        int x = gi();
        s[i] = s[i - 1] ^ x; 
        rt[i] = ++tot; 
        insert(i, 23, rt[i - 1], rt[i]); 
    } 
    for (int i = 1; i <= M; i++) { 
        char ch[5]; scanf("%s", ch);
        if (ch[0] == 'A') { 
            int x = gi(); 
            rt[++N] = ++tot; 
            s[N] = s[N - 1] ^ x;
            insert(N, 23, rt[N - 1], rt[N]);
        } else {
            int l = gi(), r = gi(), x = gi();
            printf("%d\n", query(rt[r - 1], x ^ s[N], 23, l - 1)); 
        } 
    } 
    return 0; 
}