4260: Codechef REBXOR

本文介绍了一种用于计算数组中区间异或最大值的有效算法。通过构建前缀异或数组,并利用字典树进行查询与更新,可以快速找到任意指定区间内的最大异或值。该方法涉及异或运算特性、字典树数据结构的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

做法:

维护异或和 由异或的性质 如果要找一个区间异或最大值的话 一定是sum[r+1]^sum[l] 

这样l之前的数被异或了两次就消失了。 剩下则是l到r的异或值。

可以从左到右维护一次l[]然后清0 

从右到左维护一次r[]

最后求一下max

#include<stdio.h>
#include<iostream>
#include<string.h>

#define me(x) memset(x,0,sizeof(x))
#define LL long long
#define close() ios::sync_with_stdio(0); cin.tie(0);
using namespace std;

const int N=4e5+10;
int next[N*32][2];
LL val[N*32];
int st,v[N],l[N],r[N],vt[N];
void init()
{
    me(next[0]);
    me(val);
    st=1;
    me(vt);
}
void insert(LL x)
{
    int u=0;
    for(int i=32;i>=0;i--)
    {
        int c=((x>>i)&1);
        if(!next[u][c])
        {
            me(next[st]);
            next[u][c]=st++;
        }
        u=next[u][c];
        ++val[u];
    }
}
void _delete(LL x)
{
    int u=0;
    for (int i=32; i>=0; --i)
    {
        int c=((x>>i)&1);
        u=next[u][c];
        --val[u];
    }
}
int query(LL x)
{
    int t=0;
    int ans=0;
    for(int i=32;i>=0;i--)
    {
        int k=((x>>i)&1);
        if(k==1)
        {
            if(next[t][0]&&val[next[t][0]])
            {
                ans+=1<<i;
                t=next[t][0];
            }
            else t=next[t][1];
        }
        else
        {
            if(next[t][1]&&val[next[t][1]])
            {
                ans+=1<<i;
                t=next[t][1];
            }
            else t=next[t][0];
        }
    }
    return ans;
}
int main()
{
    int n;
    init();
    close();
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>v[i];
    for(int i=1;i<=n;i++)
        vt[i]=v[i]^vt[i-1];
    vt[0]=0;vt[n+1]=0;
    for(int i=0;i<=n;i++)
    {
        l[i]=max(l[i-1],query(vt[i]));
        insert(vt[i]);
    }
    init();
    for(int i=n;i>0;i--)
        vt[i]=v[i]^vt[i+1];
    for(int i=n+1;i>=1;i--)
    {
        r[i]=max(query(vt[i]),r[i+1]);
        insert(vt[i]);
    }
    int ans=0;
    for(int i=1;i<n;i++)
        ans=max(ans,l[i]+r[i+1]);
    cout<<ans<<endl;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值