UVALive4682 XOR Sum

UVALive4682 XOR Sum

题意

给定一个数组, 求连续子序列中异或值最大的值.

题解

假设答案区间为 [L, R], 则答案为 XOR[L, R], 可以将区间分解为 XOR[L,R] == XOR[0, L - 1] ^ XOR[L, R],

因此

  1. 不断更新所以数字的 前缀异或和, 将每一个前缀异或和 都 保存到 01Trie
  2. 01Trie 中查询与它 异或值最大 的 前缀异或和
  3. 根据 Step2 的结果, 更新 ans. 重复第一步, 直至无剩余元素.

需要注意的是, 对于样例中的 3 8 2 6 4 的 前缀异或和分别 为 3 11 9 15 11, 最大值为15, 区间为 [0, 4), 因此每个Trie的初始状态应存在 0.

AC代码

#include <cstdio>
using namespace std;
int max(int a, int b) {
    return a > b ? a : b;
}
struct BinTrie {
    BinTrie* next[2];
    BinTrie() {
        next[0] = next[1] = NULL;
    }
};
void insertNum(BinTrie* root, unsigned num) {
    BinTrie* p = root;
    for(int i = 31; i >= 0; i--) {
        int index = (num >> i) & 1;
        if(!p->next[index])
            p->next[index] = new BinTrie();
        p = p->next[index];
    }
}
unsigned queryDiff(BinTrie* root, unsigned num) {
    num = ~num;
    BinTrie* p = root;
    unsigned ret = 0;
    for(int i = 31; i >= 0; i--) {
        int index = (num >> i) & 1;
        if(!p->next[index])
            index = 1 - index;
        ret += (index << i);
        p = p->next[index];
    }
    return ret;
}
int main() {
    int nTest; scanf("%d", &nTest);
    while(nTest--) {
        int nNum; scanf("%d", &nNum);
        unsigned pre = 0, ans = 0;
        BinTrie* root = new BinTrie();
        // 保证了 [0, x) 区间的合理性
        // 否则对于 15 来说, Trie中最大不同的前缀异或和 queryDiff(root, pre) 并不为 0
        insertNum(root, 0);
        while(nNum--) {
            unsigned num; scanf("%u", &num);
            pre = pre ^ num;
            insertNum(root, pre);
            ans = max(ans, queryDiff(root, pre) ^ pre);
        }
        printf("%u\n", ans);
    }
    return 0;
}

转载于:https://www.cnblogs.com/1pha/p/8721373.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值