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;
    }
    
  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/ke-xin/p/13900243.html
Copyright © 2011-2022 走看看