BZOJ4260: Codechef REBXOR 01字典树

Description
给出一个长度为n的序列。
求出l1,r1,l2,r2,使得a[l1]^a[l1+1]…a[r1]+a[l2]^a[l2+1]…a[r2]最大,且1 <= l1 <= r1 < l2 <= r2 <= n


Sample Input
5
1 2 3 1 2


Sample Output
6


这道题是01字典树的版题,你就用一个数的二进制从最高位建字典树,且保留前导0.
然后我们维护两个数组,lmax[i]表示1~i这一区间l~r异或和的最大值,rmax[i]即反之。
先考虑求lmax,我们考虑按顺序建01字典树,对于当前的一个r,如果当前最高位为hh,当前的x如果存在hh^1这个孩子,肯定考虑,往hh^1这个孩子走,这样求即可。
rmax反之。。。


#include <cstdio>
#include <cstring>

using namespace std;
int _max(int x, int y) {return x > y ? x : y;}

struct trnode {
    int c[2];
} t[30 * 410000]; int cnt;
int a[410000], lmax[410000], rmax[410000];

void clean(int u) {
    t[u].c[0] = t[u].c[1] = 0;
}

void Link(int d) {
    int x = 0;
    for(int i = 30; i >= 0; i--) {
        int hh = 0;
        if(d >= (1 << i)) hh = 1, d -= (1 << i);
        if(!t[x].c[hh]) clean(cnt + 1), t[x].c[hh] = ++cnt;
        x = t[x].c[hh];
    }
}

int query(int d) {
    int x = 0, ans = 0;
    for(int i = 30; i >= 0; i--) {
        int hh = 0;
        if(d >= (1 << i)) hh = 1, d -= (1 << i);
        if(t[x].c[hh ^ 1]) ans += (1 << i), x = t[x].c[hh ^ 1];
        else x = t[x].c[hh];
    }
    return ans;
}

int main() {
    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    cnt = 0; clean(0); Link(0);
    int now = 0;
    for(int i = 1; i <= n; i++) {
        now ^= a[i]; Link(now);
        int yy = query(now);
        lmax[i] = _max(lmax[i - 1], yy);
    }
    cnt = 0; clean(0); Link(0);
    now = 0;
    for(int i = n; i >= 1; i--) {
        now ^= a[i]; Link(now);
        int yy = query(now);
        rmax[i] = _max(rmax[i + 1], yy);
    }
    int ans = 0;
    for(int i = 0; i <= n; i++) ans = _max(ans, lmax[i] + rmax[i + 1]);
    printf("%d\n", ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值