昨天遇到一个非常神奇的事情,异或也能维护前缀和?


有两个例题:

例一、子段异或

描述:

给出长度为n的数列,问 异或值为0的子段一共有多少?

思路:

之前有一个考前缀和的,求子段和为0的子段个数,做法是这样的:
始终取前缀和,如果该位置的前缀和sum之前出现过,那么那次出现的位置到当前位置这一段总和为0。map存下sum出现的次数。遍历到当前位置,map[sum]便是以当前位置结尾的,子段和为0的子段个数。

其实这道题也是这个思路:
始终取前缀异或,如果当前位置的前缀异或sxor之前出现过,那么那次出现的位置到当前位置这一段的异或值为0。map存下sxor出现次数…

为什么异或也能这样处理呢?

因为:x^x=0,而且异或满足交换律。
所以当前的前缀异或sxor之前出现过,说明中间的那些x都被抵消掉了,也就是中间子段的异或为0了。
如:5 = 5^2^3^4^2^3^4

Code:

std::map<ll, ll> mp;
ll a[maxn],b[maxn];
int main(){int n;cin >> n;ll ans = 0;mp[0]=1;for(int i = 1; i <= n; i++){cin >> a[i];b[i] = a[i] ^ b[i - 1];ans += mp[b[i]];mp[b[i]]++;cout << ans << endl;}cout << ans << endl;return 0;
}
//代码来源:https://www.cnblogs.com/Emcikem/p/12296228.html

例二、异或差分

描述:

给长度为 n 的数列,m 个区间操作 l,r,xl,r,xl,r,x,每次将[l,r][l,r][l,r]中的每个值都异或上 xxx。
输出最终的数列。

思路:

这不和之前的前缀和差分的描述一样么?
但是能用差分么?可以。

先维护异或差分:当前位置 b[i]b[i]b[i] 为当前位置 a[i]a[i]a[i] 异或上 a[i−1]a[i-1]a[i−1]。
对于每个区间操作 [l,r][l,r][l,r],b[l]b[l]b[l] 异或上 xxx,b[r+1]b[r+1]b[r+1] 异或上 xxx。
最终求一遍前缀异或就行了。

因为:
把区间最左端异或上x,那么最终求前缀异或的时候,后面所有值都会异或上x。但是区间最右端+1的位置也异或x,那么两个相同的值异或就变为0了,那后面的值就不会再异或x了,正好只将区间中的所有值异或。

和前缀和差分有异曲同工之妙!

Code:

int A[N],C[N],L[N],R[N],V[N];
int main()
{int n,m;scanf("%d%d",&n,&m);A[0]=0;for(int i=1;i<=n;++i) scanf("%d",A+i);for(int i=1;i<=m;++i) scanf("%d%d%d",L+i,R+i,V+i);for(int i=1;i<=n;++i)C[i]=A[i-1]^A[i];for(int i=1;i<=m;++i){int l=L[i],r=R[i],v=V[i];C[l]^=v;C[r+1]^=v;}int val=0;for(int i=1;i<=n;++i){val^=C[i];printf("%d\n",val);}return 0;
}
//代码来源:https://blog.csdn.net/Dch19990825/article/details/90203832

总结一下

这两个例题都是用了同一个原理:x^x=0
所以并不是真的像前缀和那样,并不是直接将两个位置 r 和 l 的前缀异或值相减就是区间 [l+1,r][l+1,r][l+1,r] 的异或值。

同时,只有异或有这个性质,或(or)和与(and)运算都不可。


如果哪里有问题欢迎留言评论。

异或性质——前缀异或相关推荐

  1. A. Sasha and a Bit of Relax(异或的性质 + 前缀和的性质)

    Problem - 1109A - Codeforces Sasha喜欢编程.有一次,在一场很长时间的比赛中,萨沙觉得他有点累了,需要放松一下.他照做了.但由于萨沙不是一个普通人,他更喜欢不同寻常地放 ...

  2. 51Nod 2128 前缀异或 c/c++题解

    题目描述 输入一个长度为n(1 <= n <= 100000)数组a[1], a[2], -, a[n]. 输入一个询问数m(1 <= m <= 100000)和m组询问,每组 ...

  3. 前缀异或:XOR Segment (用的是前缀和的思想,所以暂且称这个方法为前缀异或)

    XOR Segment Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total S ...

  4. 【牛客每日一题】 4.13 Xorto(前缀异或和,枚举优化/映射)

    链接:https://ac.nowcoder.com/acm/problem/14247 来源:牛客网 题目描述 给定一个长度为n的整数数组,问有多少对互不重叠的非空区间,使得两个区间内的数的异或和为 ...

  5. CF1592E Bored Bakry(二进制+前缀异或和)

    CF1592E Bored Bakry description solution code description 题目链接 solution and\text{and}and如果第iii位为111, ...

  6. 【51nod - 前缀异或】 对前缀和的理解

    题干: 前缀异或  基准时间限制:2 秒 空间限制:131072 KB 分值: 5 输入一个长度为n(1 <= n <= 100000)数组a[1], a[2], ..., a[n]. 输 ...

  7. LeetCode 1829. 每个查询的最大异或值(前缀异或 + 位运算)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个 有序 数组 nums ,它由 n 个非负整数组成,同时给你一个整数 maximumBit .你需要执行以下查询 n 次: 找到一个非负整数 k ...

  8. LeetCode 1442. 形成两个异或相等数组的三元组数目(前缀异或)

    1. 题目 给你一个整数数组 arr . 现需要从数组中取三个下标 i.j 和 k ,其中 (0 <= i < j <= k < arr.length) . a 和 b 定义如 ...

  9. CodeForces.1174D.EhabandtheExpectedXORProblem(构造前缀异或和数组)

    题目链接 这道题比赛的时候没做出来,赛后补题的时候发现其实可以构造一个前缀异或和数组,然后根据初始化的第一个值进行填数,但是作为菜鸡的我虽然坚信自己的想法是正确的却想了很久也没有能够构造出来所谓的前缀 ...

最新文章

  1. 深度睡眠中,记忆如何被保持?
  2. 新手搭ssm要多久_如何快速学习ssm 框架?
  3. 简单了解音视频传输协议SDP、RTP、RTMP、SIP等
  4. 配置overlay(overlayfs)根目录挂载构建debian
  5. UA STAT687 线性模型II 最小二乘理论2 约束最小二乘估计
  6. android视频通信和web端,探讨用webrtc在手机和浏览器之间实现音视频实时通信的实施环境...
  7. 【codevs2912】反素数,好好学习天天向上
  8. csdn上传图片发现:缺少图像源文件地址
  9. Teechart图表应用技术详解—第三章之在图表上自行绘制
  10. 产品读书《产品经理的第一本书》
  11. RGB色彩模式-最广的颜色系统之一
  12. 不必学会写代码 轻松建立个人博客网站
  13. ES自动化集群搭建脚本shell
  14. 180902 逆向-网鼎(4-dalao)
  15. gis坐标|度分秒与十进制转换公式
  16. Android 9.0 一定要适配htpps请求?
  17. 2.3 响应文件(Response File)
  18. Linux 进程间通信-IPC 机制
  19. 微软IE网络霸业十年回眸
  20. Web Caching(Web缓存)

热门文章

  1. 基础类型(Primitives)与封装类型(Wrappers)的区别
  2. vue 中的插槽Slot基本使用和具名插槽
  3. JQ导出excel表格分享
  4. Android 接入融云案例
  5. 黑客操纵“肉鸡” 攻击网游服务器
  6. 【Android教程】Android Studio找不到连接的手机完全解决办法
  7. windows平台应用/开发python project
  8. centos6.7下snort2.9.9.0+base+barnyard2的安装
  9. 英语自述/English Personal Statement
  10. 快速高效的小程序反编译教程