zoukankan      html  css  js  c++  java
  • BZOJ4017 小Q的无敌异或 好题

    给一个序列

    询问这个序列

    1:所有子区间的异或值的和

    2:所有子区间的和的异或值

    第一个操作,拆二进制位,枚举右端点r,记录这个位前r个数字0/1的个数,右端点转移O(1)

    第二个操作比较复杂,对于每个右端点要询问sum[r]-sum[l-1]mod(2^(k+1))>=2^k的左端点个数(的奇偶性)

    题解用了树状数组维护,参考skywalkert,题解里对于模不等式的解释很巧妙,复习的时候多看看吧

    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    #include<string.h>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<iomanip>
    #include<stack>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define pb push_back
    #define mem(a) memset(a,0,sizeof a)
    #define FOR(a) for(int i=1;i<=a;i++)
     
    const int inf =0x3f3f3f3f; 
    const int maxn=1e5+7;
    const int mod=998244353;
    
    int n;
    int a[maxn],x[maxn],bit[maxn],ans1;
    ll s[maxn],p[maxn],ans2;
    
    void inc(int &x,int y){
    	x+=y;if(x>=mod)x-=mod;
    }
    
    void add(int x){
    	for(;x<=n;x+=~x&x+1)
    		bit[x]^=1;
    }
    int sum(int x){
    	int ret=0;
    	for(;x>=0;x-=~x&x+1)
    		ret^=bit[x];
    	return ret;
    }
    int idx(ll val){
    	//return lower_bound(p,p+n,val)-p;
    	int L=-1,R=n;
    	while(L<R){
    		int M=L+R+1>>1;
    		if(p[M]<=val)L=M;
    		else R=M-1;
    	}
    	return L;	
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		x[i]=x[i-1]^a[i];
    		s[i]=s[i-1]+a[i];
    	}	
    	//异或的和
    	for(int k=0,powk=1;k<30;++k,inc(powk,powk)){	//枚举指数
    		int cnt[2]={},tmp=0;
    		for(int i=0;i<=n;i++){
    			inc(tmp,cnt[((x[i]>>k)&1)^1]);
    			++cnt[(x[i]>>k)&1];
    		}
    		inc(ans1,1ll*powk*tmp%mod);
    	}
    
    	//和的异或
    	for(int k=0;(1ll<<k)<=s[n];++k){
    		int tmp=0;
    		for(int i=0;i<=n;i++){
    			p[i]=s[i]&((1ll<<k+1)-1);	//取模
    		}
    		sort(p,p+n+1);
    		memset(bit,0,sizeof bit);
    		
    		for(int i=0;i<=n;i++){
    			ll now=s[i]&((1ll<<k+1)-1);
    			add(idx(now));
    			tmp^=sum(idx(now-(1ll<<k)))^sum(idx(now+(1ll<<k)))^sum(idx(now));
    		}
    
    		if(tmp)
    			ans2|=1ll<<k;
    	}
    
    	printf("%d %lld
    ",ans1,ans2);
    }
     
    

  • 相关阅读:
    Linux 下IOport编程訪问
    Xcode下执行HelloWorld
    PHP/HTML混写的四种方式总结
    php取两位小数的几种方法
    使用原生JS+CSS或HTML5实现简单的进度条和滑动条效果(精问)
    js进阶 9-7 自动计算商品价值
    html5--1.12表格详解
    html5常用标签table表格布局
    html常用属性border-radius、linear-gradient怎么使用
    类选择器选择非唯一属性无法精确取值的问题
  • 原文地址:https://www.cnblogs.com/Drenight/p/8611225.html
Copyright © 2011-2022 走看看