• Codeforces Round #173 (Div. 2) E. Sausage Maximization(字典树)


    题目大意

    转化后是这样的:给了一个长度为 n(1≤n≤105) 的数组,求一个不相交的前缀和后缀,使得这个前缀和后缀中的所有数的异或值最大

    做法分析

    如果这种题目没见过类似的话,感觉挺神的,一个长度为 105 的数组,怎么去选前缀和后缀?不过不要惊慌,题目出出来是给我们做的,总有一线生机!

    先从最暴力的开始讲起:枚举每一个后缀,让他和所有不与之相交的前缀求异或值,那么转化成了:

           给一个数 a,还有一堆数,怎么在这一堆数中找出一个数 b,a 和 b 的异或值最大?

    想想:肯定要先把 a 和这一堆数转化成二进制数,枚举 a 的最高位,要使异或值最大,那么 b 从最高位开始,就要尽量与 a 对应的位不同,对不对?

    想到这里,那就好办了:把这一堆数装进一个字典树中,当然,是从最高位开始装,然后就是在这一棵字典树中尽量找出与 a 当前位不同的数,直到找到最低位为止,那么当前路径上经过的数就是我们的数 b 了,a 异或 b 也一定是最大的

    上面的问题解决了,这道题也就迎刃而解了:先把所有的数异或起来,作为最初的后缀,而前缀是 0,先插入字典树中,然后,每次将后缀“减一”,前缀“加一”,先把前缀加入字典树中,再在字典树中查询与当前的后缀异或值最大的数

    总的时间复杂度 64*n

    参考代码

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 
     5 using namespace std;
     6 
     7 typedef long long LL;
     8 const int N=100006;
     9 
    10 LL A[N], ans, cur, New;
    11 int n;
    12 
    13 struct Trie_Tree
    14 {
    15     struct node
    16     {
    17         int next[2];
    18         void init()
    19         {
    20             next[0]=next[1]=-1;
    21         }
    22     } T[64*N];
    23     int tot;
    24 
    25     void Insert(LL val)
    26     {
    27         for(int i=63, u=0; i>=0; i--)
    28         {
    29             int id=(((1LL)<<i)&(val))!=0;
    30             if(T[u].next[id]==-1)
    31             {
    32                 T[tot].init();
    33                 T[u].next[id]=tot++;
    34             }
    35             u=T[u].next[id];
    36         }
    37     }
    38 
    39     LL Find(LL val)
    40     {
    41         LL res=0;
    42         for(int i=63, u=0; i>=0; i--)
    43         {
    44             int id=(((1LL)<<i)&(val))==0;
    45             if(T[u].next[id]==-1) id^=1;
    46             res=res*2LL+(LL)id;
    47             u=T[u].next[id];
    48         }
    49         return res;
    50     }
    51 } tree;
    52 
    53 int main()
    54 {
    55     scanf("%d", &n);
    56     cur=0, New=0;
    57     for(int i=0; i<n; i++) scanf("%I64d", &A[i]), cur^=A[i];
    58     tree.T[0].init(), tree.tot=1, ans=cur;
    59     tree.Insert(0LL);
    60     for(int i=0; i<n; i++)
    61     {
    62         New^=A[i], cur^=A[i];
    63         tree.Insert(New);
    64         LL temp=tree.Find(cur);
    65         ans=max(ans, temp^cur);
    66     }
    67     printf("%I64d\n", ans);
    68     return 0;
    69 }
    E. Sausage Maximization

    题目链接 & AC通道

    Codeforces Round #173 (Div. 2) E. Sausage Maximization

  • 相关阅读:
    Vue使用watch监听一个对象中的属性
    小程序 显示对话框 确定-取消
    【微信小程序】 wx:if 与 hidden(隐藏元素)区别
    vue项目移植tinymce踩坑
    XMLHttpRequest.withCredentials 解决跨域请求头无Cookie的问题
    appJSON["window"]["navigationBarTextStyle"] 字段需为 black 或 white
    Java写 插入 选择 冒泡 快排
    编码表理解
    Centos yum安装java jdk1.8
    Java Hibernate和.Net EntityFramework 如何在提交事务之前 就拿到需要新增实体的Id
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/3077621.html
Copyright © 2020-2023  润新知