zoukankan      html  css  js  c++  java
  • [BZOJ4260] Codechef REBXOR

    传送门 - > (bzoj4260)

    题目描述

    给定一个含N个元素的数组A,下标从1开始,请找出下面式子的最大值:
    (A[11]^ A[11+1] ^ … ^ A[r1]) + (A[12] ^ A[12+1]^ … ^A[r2])。
    其中,(1<11<rl<l2<r2<N)。式中x^y表示x和y的按位异或运算。

    输入

    输入数据的第一行包含一个整数N,表示数组中的元素个数。
    第二行包含N个整数A1,A2,…,AN。

    输出

    输出一行包含给定表达式可能的最大值。

    样例输入

    5
    1 2 3 1 2

    样例输出

    6

    提示

    对于100%的数据,(2 ≤ N ≤ 4*10^5)(0 ≤ Ai ≤ 10^9).

    题解

    题目要求求出两段区间异或和之和最大,且这两个区间是递增的,没有交集,那么可以求出前缀最大异或和lmax以及后缀最大异或和rmax,其中lmax[i]代表[1,i]中一段区间的最大异或值,rmax[i]代表[i,n]中一段区间的最大异或值
    求出这两个值后,(ans=max(ans,lmax[i]+rmax[i+1]),1<=i<=n).
    那么怎么求出lmax和rmax呢,很显然在求这两个数组时是可以使用trie树前缀异或和优化的,即trie树保存的是前缀异或和d[i],表示(1-i)的异或和.
    我们知道trie树可以线性求出两个值的最大异或和,那么d[i]^trie树中的一个值x,其中(xin({d[j]|1<=j<i})),这样就可以求出[j,i]这段区间的异或和
    假如当前我们需要求出lmax[i],且d[1]~d[i-1]均已插入trie树中,
    那么lmax[i]=max(lmax[i-1],find(d[i-1]^a[i])).其中find()函数是trie的检索函数,是用来求出最大异或和的
    至于rmax,倒着做一遍就好了
    trie树数组最大要开12000000*2,不会爆内存的

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<string>
    #include<ctime>
    #define Min(a,b) (a)<(b)?(a):(b)
    #define Max(a,b) (a)>(b)?(a):(b)
    #define in(i) (i=read())
    using namespace std;
    const double delta=0.998;
    typedef long long lol;
    int read() {
        int ans=0,f=1; char i=getchar();
        while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar();}
        return ans*f;
    }
    int n,ans,tot;
    int a[400010],d[400010],trie[12000010][2];
    int lmax[400010],rmax[400010];
    void insert(int x) {
        int p=0;
        for(int i=30;i>=0;i--) {
            int c=x>>i&1;
            if(!trie[p][c]) trie[p][c]=++tot;
            p=trie[p][c];
        }
    }
    int find(int x) {
        int ans=0,p=0;
        for(int i=30;i>=0;i--) {
            int c=x>>i&1,o=c^1;
            if(trie[p][o]) ans=ans<<1|1,p=trie[p][o];
            else ans<<=1,p=trie[p][c];
        }
        return ans;
    }
    int main()
    {
        in(n);
        for(int i=1;i<=n;i++) {
            in(a[i]);
            insert(d[i-1]);
            lmax[i]=Max(lmax[i-1],find(d[i]=d[i-1]^a[i]));
        }
        memset(trie,0,sizeof(trie)),tot=0;
        for(int i=n;i>=1;i--) {
            insert(d[i+1]);
            rmax[i]=Max(rmax[i+1],find(d[i]=d[i+1]^a[i]));
        }
        for(int i=1;i<=n;i++) 
            ans=Max(ans,lmax[i]+rmax[i+1]);
        cout<<ans<<endl;
    }
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    ubuntu11.04更改默认JDK
    10个实用的jQuery交互/通信插件和教程
    jquery 使用方法
    在没有安装 ASP.NET MVC3 的服务器上运行 MVC3
    固定 vs. 流动 vs. 弹性:哪种布局更适合你?[SM]
    提升设计品质的8种布局方案[SM]
    Ubuntu 手动安装JDK
    十个简单好用的设计技巧[SM]
    jQuery VSDoc下载地址
    Ubuntu 配置Apache+PHP+MySQL
  • 原文地址:https://www.cnblogs.com/real-l/p/9473827.html
Copyright © 2011-2022 走看看