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 }
复制代码

 

posted on   greenofyu  阅读(46)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
历史上的今天:
2020-02-09 P2921 在农场万圣节(非递归的类似于记忆化搜索的巧妙方法||记忆化搜索||tarjan)
点击右上角即可分享
微信分享提示