zoukankan      html  css  js  c++  java
  • AcWing每日一题(提高组)--牛异或

    https://www.acwing.com/problem/content/1416/

    给定一串序列,要找到异或值最大的子串。

    在保证右端点最小的前提下保证长度最小。

    对于异或的性质 a^b^a = b,可以将前缀和应用于该题。

    这样的话只需要枚举左端点和右端点,但是时间复杂度为n^2,计算之后达到1e10。

    所以就需要优化,我们可以用 Trie 树来优化上述思路。

    枚举右端点,通过Trie树将查找操作的时间复杂度降为logn。

    至于“在保证右端点最小的前提下保证长度最小”这个要求,保证右端点最小,从小开始枚举就好了,长度最小,如果两前缀异或相等,那么后者会将前者覆盖掉。

     1 #include<iostream>
     2 using namespace std;
     3 const int N=1e5+10,M=N*21;//总共有N个数,每个数的范围为0~2^21-1
     4 int s[N];
     5 int son[M][2],id[M],idx;//id用来存储以该节点做结尾的数的编号
     6 void insert(int x,int k){
     7     int p=0;
     8     for(int i=20;i>=0;i--){
     9         int u=x>>i&1;
    10         if(!son[p][u]) son[p][u]=++idx;
    11         p=son[p][u];
    12     }
    13     id[p]=k;
    14 }
    15 int query(int x){
    16     int p=0;
    17     for(int i=20;i>=0;i--){
    18         int u=x>>i&1;
    19         if(son[p][!u]) p=son[p][!u];
    20         else p=son[p][u];
    21     }
    22     return id[p];
    23 }
    24 int main(void){
    25     int n;
    26     cin>>n;
    27     for(int i=1;i<=n;i++){
    28         cin>>s[i];
    29         s[i]^=s[i-1];
    30     }
    31     int res=-1,a,b;
    32     insert(s[0],0);
    33     for(int i=1;i<=n;i++){
    34         int k=query(s[i]);
    35         if((s[i]^s[k])>res)// > 的优先级高于^
    36             res=s[i]^s[k],a=k+1,b=i;
    37         insert(s[i],i);
    38     }
    39     cout<<res<<" "<<a<<" "<<b;
    40     return 0;
    41 }
  • 相关阅读:
    mysql:基础管理、体系结构、升级降级
    Linux网络基础
    mysql 忘记本地密码
    seq命令的用法
    mysql03-SQL应用
    SolidWorks 如何改变封闭草图的背景颜色
    新版 AD 无法选中某些部件(如 Via,Pad)的问题
    安装 dot net 时出现严重错误 0x80070643 安装时发生严重错误 1603 ndp48
    IO 口扩展
    自动波特率检测
  • 原文地址:https://www.cnblogs.com/greenofyu/p/14393228.html
Copyright © 2011-2022 走看看