前缀异或:XOR Segment (用的是前缀和的思想,所以暂且称这个方法为前缀异或)
2016-03-12 13:42
423 查看
XOR Segment
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)Total Submission(s) : 34 Accepted Submission(s) : 12
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
给出 n 个数的数列,让你求出异或和为零的连续子段,如果有多个答案,要求连续字段长度最短,如果长度最短子段有多个,取最靠前的字段。异或操作体现在C++里面:^操作,两数做异或的含义是其对应的每一位二进制位做异或,例如:5 ^ 7 = (101) ^ (111) = (010) = 2
Input
第一行一个数据组数 T,(T <= 100)每组数据第一行一个 n(n <= 10^6)
第二行给出 n 个数,0 <= 数值 < 10^5
Output
每组数据输出一行子段的左右端点,如果不存在这样的字段,输出-1Sample Input
3 5 1 2 3 4 5 2 2 4 3 4 0 4
Sample Output
1 3 -1 2 2 解法思路:异或的性质是,两个相同的数异或为0,a^b^a = b; a^b^b = a; 根据这个性质,可以想到,连续异或一个序列,得到某个值,然后继续异或下去,如果再次得到这个 值,那么这两个值之间自然就有通过连续异或变为0的子序列。写法就像写前缀和一样,所以暂且称为前缀异或吧~ AC代码: [code]#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int maxn = 1e6; int a[maxn], b[maxn]; int record[maxn]; int main() { int T; cin >> T; while(T--) { int n; int left, right; scanf("%d", &n); int anslen = 1e6; memset(record, -1, sizeof(record)); record[0] = 0; b[0] = 0; a[0] = 0; for(int i = 1; i <= n;i++) { cin >> a[i]; b[i] = b[i-1]^a[i]; if(record[b[i]] == -1) record[b[i]] = i; else { if(i-record[b[i]] < anslen) { left = record[b[i]]+1; right = i; anslen = i-record[b[i]]; } record[b[i]] = i; } } if(anslen != 1e6) printf("%d %d\n", left, right); else printf("-1\n"); } return 0; }
[/code]
相关文章推荐
- 项目开发技巧
- 选择排序法
- lower_bound()和upper_bound()的简单讲解
- Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
- 搭建Hadoop2.7.2开发环境1(编译Eclipse中hadoop插件hadoop2x-eclipse-plugin)
- VIM
- 软件测试面试可能会遇到的一些问题
- ionic + 高德地图定位
- 第一次上机实验-2
- event 事件 clientX 和clientY 配合scrollTop使用, div跟着鼠标走
- 使用基于ThinkPHP3.2.3的ThinkAdmin创建手机电脑通用的表白墙(六)表白页面
- day13—HTML DOM编程
- CodeForces - 598A Tricky Sum (快速幂)
- 关于java开发技巧
- Backbone源码分析-Backbone架构+流程图
- SPRING循环依赖(circular reference)的解决方法
- 欢迎使用CSDN-markdown编辑器
- spring security执行流程图
- 面试题3 ----二维数组中的查找
- 重复登录Windows远程桌面-Autoit脚本