zoukankan      html  css  js  c++  java
  • 2020牛客寒假算法基础集训营4 D:子段异或

    D : 子段异或


    考察点 : 位运算,前缀和,异或的性质和应用
    坑点 : 0 - L 的异或值是 0 的话也是一个区间
    相同的值可能有多个,那么这时候区间就会有多个(x * (x + 1) / 2)

    关于异或的性质和应用:https://www.cnblogs.com/prjruckyone/p/12302732.html

    侃侃 :

    怎么求区间异或值为 0 的区间呢 ? 
    在求这个之前,可以想一下怎么求区间 和 为 0 的区间呢?
    我们知道一个区间和或者区间异或 [L,R] 都可以表示为 sum[R] - sum[L - 1];
    (具体可参考上面那篇博客 : [关于异或的性质和应用](https://www.cnblogs.com/prjruckyone/p/12302732.html))
    那么区间 和 怎么才会是 0 呢?是不是只有  相同的两个数相减才会 = 0,
    同样的,我们知道 相同的两个值 异或 = 0;
    那么我们只需要先求出所有的异或前缀和,然后看有多少值是相等的,然后根据相等的个数来计算区间即可。
    

    Code:

    
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long LL;
    const int maxn = 2e5 + 10;
    int sum[maxn],a[maxn];
    int n;
    
    LL cnt = 0;
    
    int main(void) {
    	scanf("%d",&n);
    	for(int i = 1; i <= n; i ++) {
    		scanf("%d",&a[i]);
    		if(i == 1) sum[i] = a[i];
    		else {
    			sum[i] = sum[i - 1] ^ a[i];
    		}
    		if(sum[i] == 0) cnt ++;
    	}
    	sort(sum + 1,sum + 1 + n);
    	LL ans = 0;
    	sum[n + 1] = -1;
    	for(int i = 1; i <= n; i ++) {
    //		if(sum[i] == 0) continue;          // 0 相等的区间也要算上
    		if(sum[i] == sum[i + 1]) {
    			ans ++;
    		} else {
    //			if(ans != 1)
    			cnt += (ans * (ans + 1) / 2) ;  // ans 至少是 1 对,
    			ans = 0;
    		}
    	}
    	cout << cnt << endl;
    	return 0;
    }
    
    
  • 相关阅读:
    20165222第八周课上补做
    20165222—第八周学习
    20165222《Java程序设计》——实验二 面向对象程序设计
    20165222 结对编程学习
    20165222 第七周学习总结
    20165222 第六周学习总结
    20165222 实验一java开发环境的熟悉
    20165222 第五周学习总结
    JSP
    Servlet
  • 原文地址:https://www.cnblogs.com/prjruckyone/p/12302842.html
Copyright © 2011-2022 走看看