• 「LOJ#10051」「一本通 2.3 例 3」Nikitosh 和异或(Trie


    题目描述

    原题来自:CODECHEF September Challenge 2015 REBXOR

    1​​r1​​<l2​​r2​​N,x⨁yxigoplus yx⨁y 表示 xxx 和 yyy 的按位异或。

    输入格式

    输出格式

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

    样例

    数据范围与提示

    5​​,0Ai​​109​​。

    题解

    首先记录异或前缀和$s[i]=a[1]⊕a[2]⊕a[3] ...⊕a[i]$。

    设$l[i]$为以$i$结尾的区间中,异或值的最大值。

    因为异或有 $x⊕x=0$ 的性质,所以区间 $[l,r]$ 的异或值

    $=a[l]⊕a[l+1]⊕...⊕a[r]$

    $=(a[1]⊕a[2]⊕a[3]...⊕a[l-1])⊕(a[1]⊕a[2]⊕a[3] ...⊕a[r])$

    $=s[l-1]⊕s[r]$,

    所以求$l[i]$,转化为找$j<i$,使得$s[j]⊕s[i]$最大。

    转化为「LOJ#10050」「一本通 2.3 例 2」The XOR Largest Pair(Trie

    以相似的方法可以求出$r[i]$(以$i$开头的区间中,异或值的最大值)。

    在实际操作的过程中可以$l[i]=max(l[i-1],find(x))$,这样$ans=max(l[i]+r[i+1])$就行了。

    书上的操作是直接$l[i]=find(x)$然后$ans=max(l[i]+r[i+1])$,感觉不能理解qwq

     1 编号     题目     状态     分数     总时间     内存     代码 / 答案文件     提交者     提交时间
     2 #237651     #10051. 「一本通 2.33」Nikitosh 和异或    Accepted     100     2765 ms     43900 KiB     C++ / 1.2 K     qwerta     2018-10-20 17:15:56
     3 
     4 #include<iostream>
     5 #include<cstring>
     6 #include<cstdio>
     7 #include<cmath>
     8 using namespace std;
     9 int s[400003];
    10 int l[400003];
    11 int r[400003];
    12 struct emm{
    13     int nxt[2];
    14 }a[12800003];
    15 int cnt=0;
    16 int b[33];
    17 void add(int x)
    18 {
    19     int j=-1;
    20     memset(b,0,sizeof(b));
    21     while(x)
    22     {
    23         b[++j]=x&1;
    24         x>>=1;
    25     }
    26     int k=0;
    27     for(int j=32;j>=0;--j)
    28     {
    29         if(!a[k].nxt[b[j]])
    30           a[k].nxt[b[j]]=++cnt;
    31         k=a[k].nxt[b[j]];
    32     }
    33     return;
    34 }
    35 int find(int x)
    36 {
    37     int now=0,k=0;
    38     for(int j=32;j>=0;--j)
    39     {
    40         if(a[k].nxt[1-b[j]])
    41         {
    42             now+=(1<<j);
    43             k=a[k].nxt[1-b[j]];
    44         }
    45         else k=a[k].nxt[b[j]];
    46     }
    47     return now;
    48 }
    49 int main()
    50 {
    51     //freopen("a.in","r",stdin);
    52     int n;
    53     scanf("%d",&n);
    54     for(int i=1;i<=n;++i)
    55       scanf("%d",&s[i]);
    56     int x=0;
    57     for(int i=1;i<=n;++i)
    58     {
    59         x^=s[i];//这里的x为前缀和
    60         add(x);
    61         l[i]=max(l[i-1],find(x));
    62     }
    63     //重做一次找r[i]
    64     memset(a,0,cnt+1);
    65     x=0,cnt=0;
    66     for(int i=n;i;--i)
    67     {
    68         x^=s[i];
    69         add(x);
    70         r[i]=max(r[i+1],find(x));
    71     }
    72     int ans=0;
    73     for(int i=1;i<n;++i)
    74     ans=max(ans,l[i]+r[i+1]);
    75     cout<<ans;
    76     return 0;
    77 }
  • 相关阅读:
    Linux问题汇总
    Linux问题汇总
    朴素贝叶斯分类器
    捕捉异常信息
    异常处理类
    sqlserver2008链接服务器的使用和oracle11g客户端修改字符集
    抛出异常
    添加水印
    验证码
    sqlserver数据库备份
  • 原文地址:https://www.cnblogs.com/qwerta/p/9822368.html
Copyright © 2020-2023  润新知