zoukankan      html  css  js  c++  java
  • 【BZOJ】4260: Codechef REBXOR【Trie树】【前后缀异或最大】

    4260: Codechef REBXOR

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 2218  Solved: 962
    [Submit][Status][Discuss]

    Description

    Input

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

    Output

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

    Sample Input

    5
    1 2 3 1 2

    Sample Output

    6

    HINT

     

    满足条件的(l1,r1,l2,r2)有:(1,2,3,3),(1,2,4,5),(3,3,4,5)。

    对于100%的数据,2 ≤ N ≤ 4*105,0 ≤ Ai ≤ 109。


    Solution

    用trie树处理出以$i$结尾的最大区间异或,前后分别扫一遍处理前缀和后缀。具体做法是将前缀或后缀插入trie树中,每次用前缀或后缀在trie树中查询异或最大,就是查询以$i$结尾的区间异或最大。

    然后每个位置与前面取max,最后合并统计答案即可。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    
    int n, a[400005], l[400005], r[400005];
    int son[31*400005][2], tail;
    
    void read(int &x) {
        x = 0; char ch = getchar();
        while(ch > '9' || ch < '0')    ch = getchar();
        while(ch >= '0' && ch <= '9') {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
    }
    
    void insert(int x) {
        int nd = 0;
        for(int i = 30; ~i; i --) {
            int t = 1 & (x >> i);
            if(!son[nd][t])    son[nd][t] = ++ tail;
            nd = son[nd][t];
        }
    }
    
    int query(int x) {
        int nd = 0, ans = 0;
        for(int i = 30; ~i; i --) {
            int t = 1 & (x >> i);
            if(son[nd][!t]) {
                ans += (1 << i); nd = son[nd][!t];
            } else if(son[nd][t])    nd = son[nd][t];
            else break;
        }
        return ans;
    }
    
    int main() {
        read(n);
        int now = 0;
        insert(0);
        for(int i = 1; i <= n; i ++) {
            read(a[i]); now ^= a[i];
            insert(now);
            l[i] = query(now);
        }
        for(int i = 1; i <= n; i ++)    l[i] = max(l[i], l[i - 1]);
        now = 0;
        memset(son, 0, sizeof(son)); tail = 0;
        insert(0);
        for(int i = n; i >= 1; i --) {
            now ^= a[i];
            insert(now);
            r[i] = query(now);
        }
        for(int i = n; i >= 1; i --)    r[i] = max(r[i], r[i + 1]);
        long long ans = 0;
        for(int i = 1; i <= n; i ++)
            ans = max(ans, 1ll * (l[i] + r[i + 1]));
        printf("%lld", ans);
        return 0;
    } 
     
  • 相关阅读:
    简述at和crontab命令
    自建yum仓库,分别为网络源和本地源
    简述rpm与yum命令的常见选项
    用户目录权限管理.手动添加用户.截取用户信息
    总结描述用户和组管理类命令的使用方法,系统用户相关信息,取出主机IP地址
    Android独立交叉编译环境搭建
    Python编程总结之常用三方模块
    GDB常用命令简介
    linux内核中task_struct与thread_info及stack三者的关系
    在Linux-PC上建立kdump调试环境
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/9834735.html
Copyright © 2011-2022 走看看