zoukankan      html  css  js  c++  java
  • BZOJ 4260: Codechef REBXOR(01trie+思维)

    求两个不相交区间异或和的和最大.

    设l[i]是1~i一段区间的最大异或和,r[i]是i~n一段区间的最大异或和,题意就是求max(l[i]+r[i+1]);

    那么只要求l,r数组。

    设num数组是个前缀异或和,根据异或的性质,我们要求i~j的异或和就是num[i]^num[j],所以对于l数组,我们要求出max(num[i]^num[j]),r数组用后缀异或和同理.

    l[i]=max(l[i-1],find(num[i-1]^a[i])) l[i-1]表示区间不包括i,否则就是用find函数找区间包括i的值.find函数就是再trie树上尽量往相反的方向爬。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=4e5+50;
    12 const int MOD=1e9+7;
    13 using namespace std;
    14 int n;
    15 int tot=1;
    16 int a[N];
    17 int num[N],l[N],r[N];
    18 int trie[N*31][2];
    19 int ans;
    20 int read()
    21 {
    22     int s=0,t=1; char c;
    23     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    24     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    25     return s*t;
    26 }
    27 ll readl()
    28 {
    29     ll s=0,t=1; char c;
    30     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    31     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    32     return s*t;
    33 }
    34 void insert(int x)
    35 {
    36     int u=1;
    37     for (int i=31;i>=0;i--){
    38       int c=((1<<i)&x)>0;
    39       if (!trie[u][c]) trie[u][c]=++tot;
    40       u=trie[u][c];
    41     }
    42 }
    43 int find(int x)
    44 {
    45     int u=1,res=0;
    46     for (int i=31;i>=0;i--){
    47       int c=((1<<i)&x)>0;
    48       if (trie[u][1-c]) u=trie[u][1-c],res+=(1<<i);
    49       else u=trie[u][c];
    50     }
    51     return res;
    52 }
    53 int main()
    54 {
    55     n=read();
    56     for (int i=1;i<=n;i++){
    57       a[i]=read();
    58       insert(num[i-1]);
    59       num[i]=num[i-1]^a[i];
    60       l[i]=max(l[i-1],find(num[i]));
    61     }
    62     memset(trie,0,sizeof(trie));
    63     for (int i=n;i;i--){
    64       insert(num[i+1]);
    65       num[i]=num[i+1]^a[i];
    66       r[i]=max(r[i+1],find(num[i]));
    67       ans=max(ans,l[i]+r[i+1]);
    68     }
    69     out(ans);
    70     return 0;
    71 }
    72     
    73     
    View Code
  • 相关阅读:
    button 垂直分布
    GitHub上值得关注的iOS开源项目
    电脑连接网络(网络正常),但不能上网,登录网页提示dns_probe_finished_no_internet
    android 模拟应用因内存不足被后台杀死命令
    android 屏幕划分
    android 没有root的手机导出数据库
    移动硬盘不能识别,设备管理器中显示黄色感叹号
    低功耗蓝牙开发(BLE)
    音视频学习笔记
    Java中为什么要使用线程池?如何使用?
  • 原文地址:https://www.cnblogs.com/Kaleidoscope233/p/9563206.html
Copyright © 2011-2022 走看看