zoukankan      html  css  js  c++  java
  • CF242E XOR on Segment

    CF242E XOR on Segment

    区间异或不好直接维护,于是我们考虑将所有数二进制分解。

    我们把每一位单独提出来做,那么对于每一位,异或要么不变,要么取反,而位与位之间的操作是独立的!建一棵线段树维护每一位的信息,那么只要维护:
    1.区间取反(0变1,1变0)
    2.区间求和

    即可。这个利用线段树+标记能够很轻松的实现。

    所以总复杂度为(O(nk log n)),其中k为二进制的位数,这里(k ≤20)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
     
    using namespace std;
    typedef long long ll;
    const int N=400005;
    inline int read() {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    int n,m,a[N];
    ll val[21][N];
    bool tag[21][N];
    
    #define ls (p<<1)
    #define rs (p<<1|1)
    #define mid ((l+r)>>1)
    void build(int l,int r,int p) {
    	if(l==r) {
    		for(int i=0;i<=20;i++) 
    			if(a[l]&(1<<i)) 
    				val[i][p]=1;
    		return;
    	} 
    	build(l,mid,ls);
    	build(mid+1,r,rs);
    	for(int i=0;i<=20;i++)
    		val[i][p]=val[i][ls]+val[i][rs];
    }
    
    void pushdw(int p,int l,int r,int i) {
    	tag[i][ls]^=tag[i][p];
    	tag[i][rs]^=tag[i][p];
    	if(!tag[i][p]) return;
    	val[i][ls]=mid-l+1-val[i][ls];
    	val[i][rs]=r-mid-val[i][rs];
    	tag[i][p]=0;
    }
    
    void modify(int l,int r,int L,int R,int i,int p) {
    	if(L<=l&&r<=R) {
    		val[i][p]=r-l+1-val[i][p];
    		tag[i][p]^=1;
    		return;
    	}
    	pushdw(p,l,r,i);
    	if(L<=mid) modify(l,mid,L,R,i,ls);
    	if(R>mid) modify(mid+1,r,L,R,i,rs);
    	val[i][p]=val[i][ls]+val[i][rs];
    }
    
    ll query(int l,int r,int L,int R,int p) {
    	if(L<=l&&r<=R) {
    		ll ans=0;
    		for(int i=0;i<=20;i++)
    			ans+=(val[i][p]<<i);
    		return ans;
    	}
    	for(int i=0;i<=20;i++)
    		pushdw(p,l,r,i);
    	ll ans=0;
    	if(L<=mid) ans+=query(l,mid,L,R,ls);
    	if(R>mid) ans+=query(mid+1,r,L,R,rs);
    	return ans;
    }
    int main() {
    	n=read();
    	for(int i=1;i<=n;i++) a[i]=read();
    	build(1,n,1);
    	m=read();
    	while(m--) {
    		int op=read(),l=read(),r=read();
    		if(op==1) {
    			printf("%lld
    ",query(1,n,l,r,1));
    		} else {
    			int x=read();
    			for(int i=0;i<=20;i++)
    				if(x&(1<<i))
    					modify(1,n,l,r,i,1);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    外星人(alien)
    6. 第 6 章 函数
    5. 第 5 章 循环
    4. 第 4 章 条件选择
    3. 第 3 章 表达式和交互
    2. 第 2 章 C++简介
    1. 第 1 章 计算机和编程简介
    24. 蛇形填数
    23. 开灯问题
    12. aabb
  • 原文地址:https://www.cnblogs.com/ke-xin/p/13900243.html
Copyright © 2011-2022 走看看