【Trie 字典树】Nikitosh and xor(01字典树)

【Trie 字典树】Nikitosh and xor

时间限制: 1 Sec  内存限制: 128 MB
提交: 4  解决: 2

 

题目描述

Nikitosh the painter has a 1-indexed array A of N elements. He wants to find the maximum value of expression 

(A[l1] ⊕ A[l1 + 1] ⊕ ... ⊕ A[r1]) + (A[l2] ⊕ A[l2 + 1] ⊕ ... ⊕ A[r2]) where 1 ≤ l1 ≤ r1 < l2 ≤ r2 ≤ N.

Here, x ⊕ y means the bitwise XOR of x and y.

Because Nikitosh is a painter and not a mathematician, you need to help him in this task.

输入

The first line contains one integer N, denoting the number of elements in the array.

The second line contains N space-separated integers, denoting A1, A2, ... , AN.

输出

Output a single integer denoting the maximum possible value of the given expression.

样例输入

5
1 2 3 1 2

样例输出

6

提示

2 ≤ N ≤ 4*105
0 ≤ Ai ≤ 109

题目大意:给你n个数字,让你求两段互不交叉的序列分别的亦或和之和的最大值

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 4e5 + 5;
int trie[maxn * 30][2];
int tot = 1;
ll poww[40];
ll l[maxn],r[maxn];
ll zz[maxn];
void insert(ll p)
{
    int tmp = 1;
    for (int i = 30; i >= 0; --i)
    {
        int tmpp;
        if (p & poww[i])
            tmpp = 1;
        else
            tmpp = 0;
        if (!trie[tmp][tmpp])
            trie[tmp][tmpp] = ++tot;
        tmp = trie[tmp][tmpp];
    }
}
ll findd(ll p)
{
    int tmp = 1;
    ll ans = 0;
    for (int i = 30; i >= 0; --i)
    {
        int tmpp;
        if (p & poww[i])
            tmpp = 1;
        else
            tmpp = 0;
        if (trie[tmp][tmpp ^ 1])
        {
            ans += poww[i];
            tmp = trie[tmp][tmpp ^ 1];
        }
        else
            tmp = trie[tmp][tmpp];
    }
    return ans;
}
void init()
{
    poww[0] = 1;
    for (int i = 1; i <= 30; ++i)
        poww[i] = poww[i - 1] << 1;
}
int main()
{
//    freopen("in.txt", "r", stdin);
    int n;
    init();
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
    {
        ll tmp;
        scanf("%lld", &tmp);
        zz[i] = tmp ^ zz[i - 1];
    }
    insert(0);
    for (int i = 1; i <= n; ++i)
    {
        l[i] = max(l[i - 1], findd(zz[i]));
        insert(zz[i]);
    }   //从左往右插入字典树
    memset(trie, 0, sizeof(trie));
    tot = 1;
    for (int i = n; i > 0; --i)
    {
        r[i] = max(r[i + 1], findd(zz[i]));
        insert(zz[i]);
    } 从右往左插入字典树
    ll ans = 0;
    for (int i = 1; i <= n; ++i)
        ans = max(ans, l[i] + r[i]);
    printf("%lld\n", ans);
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值