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

    CF242E XOR on Segment

    洛谷传送门

    题意翻译

    • 给定nn 个数的序列 aa。mm 次操作,操作有两种:

      1. 求 displaystylesum_{i=l}^r a_ii=lrai
    1. 把 a_lsim a_ra**la**r 异或上 xx
    • 1le nle 10^51≤n≤105,1le mle 5 imes 10^41≤m≤5×104,0le a_ile 10^60≤a**i≤106,1le xle 10^61≤x≤106。

    题解:

    由于位运算和求和操作不兼容,所以不是裸的线段树的题。

    介绍一种操作:拆位。

    具体一些,因为位运算和求和不兼容,但是保证位运算正确可以由此维护和(按位乘2的整数次幂再相加),反之,只维护和的正确性不能保证位运算正确。所以我们用拆位来维护每一位。

    为了保证和的可求性,我们对于每个节点维护(tree[pos].val[i])表示当前节点的第(i)位有多少个1.

    这时,如果要区间异或上一个(x),如果(x)的对应位为1就要取反,反之不变。这样的话,我们就维护好了位运算的正确性。要求和的时候再累加即可。

    记得开longlong

    代码:

    #include<cstdio>
    #define lson pos<<1
    #define rson pos<<1|1
    #define int long long
    using namespace std;
    const int maxn=1e5+5;
    int n,m;
    int a[maxn];
    struct segment_tree
    {
    	int val[22];
    	int sum;
    }tree[maxn<<2];
    int lazy[maxn<<2];
    void pushup(int pos)
    {
    	for(int i=0;i<=20;i++)
    		tree[pos].val[i]=tree[lson].val[i]+tree[rson].val[i];
    	tree[pos].sum=tree[lson].sum+tree[rson].sum;
    }
    void build(int pos,int l,int r)
    {
    	int mid=(l+r)>>1;
    	if(l==r)
    	{
    		for(int i=0;i<=20;i++)
    			if(a[l]>>i&1)
    				tree[pos].val[i]=1;
    		tree[pos].sum=a[l];
    		return;
    	}
    	build(lson,l,mid);
    	build(rson,mid+1,r);
    	pushup(pos);
    }
    int qpow(int a,int b)
    {
    	int ret=1;
    	while(b)
    	{
    		if(b&1)
    			ret*=a;
    		a*=a;
    		b>>=1;
    	}
    	return ret;
    }
    void mark(int pos,int l,int r,int k)
    {
    	int tmp=0;
    	for(int i=0;i<=20;i++)
    		if(k>>i&1)
    			tree[pos].val[i]=(r-l+1)-tree[pos].val[i];
    	for(int i=0;i<=20;i++)
    		tmp+=(qpow(2,i)*tree[pos].val[i]);
    	tree[pos].sum=tmp;
    	lazy[pos]^=k;
    }
    void pushdown(int pos,int l,int r)
    {
    	int mid=(l+r)>>1;
    	mark(lson,l,mid,lazy[pos]);
    	mark(rson,mid+1,r,lazy[pos]);
    	lazy[pos]=0;
    }
    void update(int pos,int l,int r,int x,int y,int k)
    {
    	int mid=(l+r)>>1;
    	if(x<=l && r<=y)
    	{
    		mark(pos,l,r,k);
    		return;
    	}
    	if(lazy[pos])
    		pushdown(pos,l,r);
    	if(x<=mid)
    		update(lson,l,mid,x,y,k);
    	if(y>mid)
    		update(rson,mid+1,r,x,y,k);
    	pushup(pos);
    }
    int query(int pos,int l,int r,int x,int y)
    {
    	int ret=0;
    	int mid=(l+r)>>1;
    	if(x<=l && r<=y)
    		return tree[pos].sum;
    	if(lazy[pos])
    		pushdown(pos,l,r);
    	if(x<=mid)
    		ret+=query(lson,l,mid,x,y);
    	if(y>mid)
    		ret+=query(rson,mid+1,r,x,y);
    	return ret;
    }
    signed main()
    {
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%lld",&a[i]);
    	build(1,1,n);
    	scanf("%lld",&m);
    	for(int i=1;i<=m;i++)
    	{
    		int opt,x,y,k;
    		scanf("%lld%lld%lld",&opt,&x,&y);
    		if(opt==1)
    			printf("%lld
    ",query(1,1,n,x,y));
    		else
    		{
    			scanf("%lld",&k);
    			update(1,1,n,x,y,k);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    洛谷 P1763 状态压缩dp+容斥原理
    hdu4612 Warm up 缩点+树的直径
    UVA-315 无向图求割点个数
    mysql 严格模式 Strict Mode说明
    bak文件恢复成 SQL2005 数据库 的全程讲解
    vps(windows2003)安全设置参考
    window下lamp环境搭建
    centos虚拟机配置网卡连接
    linux Tar 命令参数详解
    linux 打包和压缩的概念和区别
  • 原文地址:https://www.cnblogs.com/fusiwei/p/14034122.html
Copyright © 2011-2022 走看看