【BZOJ3261】最大异或和【可持久化Trie树】

Trie维护序列前缀异或和,然后贪心找就可以啦。

#include <cstdio>

const int maxn = 600005, maxd = 26, maxnode = maxn * maxd;

int n, m, bin[maxd], num[maxn], son[maxnode][2], sum[maxnode], root[maxn], triecnt;

inline int iread() {
    int f = 1, x = 0; char ch = getchar();
    for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
    for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
    return f * x;
}

inline void insert(int &pos, int c) {
    int now = ++triecnt, last = pos; pos = now;
    for(int i = maxd - 1; i >= 0; i--) {
        son[now][0] = son[last][0]; son[now][1] = son[last][1];
        sum[now] = sum[last] + 1;
        bool ind = c & bin[i];
        last = son[last][ind];
        now = son[now][ind] = ++triecnt;
    }
    sum[now] = sum[last] + 1;
}

inline int query(int l, int r, int c) {
    int ans = 0;
    for(int i = maxd - 1; i >= 0; i--) {
        bool ind = c & bin[i];
        if(sum[son[r][ind ^ 1]] - sum[son[l][ind ^ 1]])
            ans += bin[i], l = son[l][ind ^ 1], r = son[r][ind ^ 1];
        else l = son[l][ind], r = son[r][ind];
    }
    return ans;
}		

int main() {
    freopen("xor.in", "r", stdin); freopen("xor.out", "w", stdout);

    bin[0] = 1; for(int i = 1; i < maxd; i++) bin[i] = bin[i - 1] << 1;

    n = iread(); m = iread(); num[1] = 0; ++n;
    for(int i = 2; i <= n; i++) num[i] = iread() ^ num[i - 1];

    for(int i = 1; i <= n; i++) insert(root[i] = root[i - 1], num[i]);
    
    while(m--) {
        char ch = getchar(); for(; ch != 'A' && ch != 'Q'; ch = getchar());
        if(ch == 'A') {
            ++n; num[n] = iread() ^ num[n - 1];
            insert(root[n] = root[n - 1], num[n]);
        } else {
            int l = iread(), r = iread(), c = iread();
            printf("%d\n", query(root[l - 1], root[r], c ^ num[n]));
        }
    }
    return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/BraketBN/article/details/50756429
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞