zoukankan      html  css  js  c++  java
  • [TJOI2017] 异或和

    题面

        由于本题求和的优先级高于异或,所以最后其实是一坨求和之后的数再异或起来,于是我们就可以拆位做啦。

        然后原问题简化成了:对于每一位,有多少区间和在这一位上是1。

        假如现在处理到 2^i 这位,然后我们枚举区间右端点j,想要可以快速找到所有左端点l,满足 sum[j] - sum[l-1] 在 2^i 这位为1(为0不用管,对异或无影响)。

        可以发现 sum[j] > sum[l-1] 必然成立,不妨设 lef[x] 为每个位置的数 仅保留后 i 位 得到的数 (即2^0,2^1,.....,2^(i-1)这些位),那么可以得到:

            lef[x] >= lef[l-1] 时,当且仅当 sum[j]^sum[l-1] 在 2^i 这位为1时,j与l-1是一个我们需要的区间;

            类似的,lef[x]<lef[l-1]时,当且仅当 sum[j]^sum[l-1] 在 2^i 这位为0时,j与l-1是一个我们需要的区间;

    然后这就是个树状数组题了23333(后面还有个细节,因为树状数组里面最小的下标是1,所以要对下标做一些修改)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=1e5+5,M=1e6+5;
    
    inline int read(){
        int x=0; char ch=getchar();
        for(;!isdigit(ch);ch=getchar());
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x;
    }
    
    int n,a[N],f[2][M],ans,i,now,oe; 
    
    inline void update(int T,int x){
    	for(;x<=i;x+=x&-x) f[T][x]^=1;
    }
    
    inline int query(int T,int x){
    	int an=0;
    	for(;x;x-=x&-x) an^=f[T][x];
    	return an;
    }
    
    int main(){
    	n=read();
    	for(i=1;i<=n;i++) a[i]=read()+a[i-1];
    	
    	for(i=1,now=0,oe;i<=a[n];now|=i,i<<=1){
    		memset(f,0,sizeof(f)),oe=0;
    		
    		update(0,1);
    		for(int j=1,u,p;j<=n;j++){
    			u=(a[j]&i)?1:0,p=(a[j]&now)+1;
    			oe^=query(u^1,p)^query(u,i)^query(u,p);
    			update(u,p);
    		}
    		
    		ans+=i*oe;
    	}
    	
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    Spring-12-spring整合Mybatis
    Spring-11-AOP面向切面编程
    jQuery选择器之表单元素选择器
    phpsmarty分配变量
    angular
    ajax 第四步
    ajax第三步
    php+ajax+jq
    二十三种设计模式[4]
    二十三种设计模式[3]
  • 原文地址:https://www.cnblogs.com/JYYHH/p/11302201.html
Copyright © 2011-2022 走看看