zoukankan      html  css  js  c++  java
  • FZU-2105 Digits Count (两种标记成段更新)

    题目大意:给n个0~15之间的数,有3种更新操作,1种询问操作。3种更新操作是:1、让某个闭区间的所有数字与一个0~15之间的数字进行逻辑与运算;2、让某个闭区间的所有数字与一个0~15之间的数字进行逻辑或运算;3、让某个闭区间的所有数字与一个0~15之间的数字进行异或运算。一种询问操作是询问某个闭区间的所有数字之和。

    题目分析:所有的输入数字都是在0~15之间,可以二进制中的每一位建立线段树,建立四棵。3种更新操作实际上只有两种,即区间置位和区间反转。用两个懒惰标记,当进行区间置位更新的时候,要清除已经存在的反转标记,这样就能保证标记下传时两种标记下传的先后次序。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    # define LL long long
    
    const int N=1000000;
    
    int n,m;
    int a[N+5];
    int tr[4][N*4+5];
    int lazy[4][N*4+5];
    int lazy_xor[4][N*4+5];
    char com[5];
    
    void pushDown(int id,int rt,int l,int r)
    {
    	int mid=l+(r-l)/2;
    	if(lazy[id][rt]!=-1){
    		lazy_xor[id][rt<<1]=lazy_xor[id][rt<<1|1]=0;
    		lazy[id][rt<<1]=lazy[id][rt<<1|1]=lazy[id][rt];
    		tr[id][rt<<1]=lazy[id][rt]*(mid-l+1);
    		tr[id][rt<<1|1]=lazy[id][rt]*(r-mid);
    		lazy[id][rt]=-1;
    	}
    	int &q=lazy_xor[id][rt];
    	if(q==1){
    		lazy_xor[id][rt<<1]^=1;
    		lazy_xor[id][rt<<1|1]^=1;
    		tr[id][rt<<1]=mid-l+1-tr[id][rt<<1];
    		tr[id][rt<<1|1]=r-mid-tr[id][rt<<1|1];
    		q=0;
    	}
    }
    
    void pushUp(int id,int rt)
    {
    	tr[id][rt]=tr[id][rt<<1]+tr[id][rt<<1|1];
    }
    
    void build(int id,int rt,int l,int r)
    {
    	lazy[id][rt]=-1;
    	lazy_xor[id][rt]=0;
    	if(l==r){
    		if((a[r]&(1<<id))>0) tr[id][rt]=1;
    		else tr[id][rt]=0;
    	}else{
    		int mid=l+(r-l)/2;
    		build(id,rt<<1,l,mid);
    		build(id,rt<<1|1,mid+1,r);
    		pushUp(id,rt);
    	}
    }
    
    void update(int id,int rt,int l,int r,int L,int R,int x)
    {
    	if(L<=l&&r<=R){
    		if(x==2){
    			if(lazy[id][rt]!=-1) lazy[id][rt]^=1;
    			else lazy_xor[id][rt]^=1;
    			tr[id][rt]=(r-l+1)-tr[id][rt];
    		}else{
    			lazy[id][rt]=x;
    			lazy_xor[id][rt]=0;
    			tr[id][rt]=x*(r-l+1);
    		}
    	}else{
    		pushDown(id,rt,l,r);
    		int mid=l+(r-l)/2;
    		if(L<=mid) update(id,rt<<1,l,mid,L,R,x);
    		if(R>mid) update(id,rt<<1|1,mid+1,r,L,R,x);
    		pushUp(id,rt);
    	}
    }
    
    LL query(int id,int rt,int l,int r,int L,int R)
    {
    	if(L<=l&&r<=R) return tr[id][rt];
    	pushDown(id,rt,l,r);
    	int mid=l+(r-l)/2;
    	LL res=0;
    	if(L<=mid) res+=query(id,rt<<1,l,mid,L,R);
    	if(R>mid) res+=query(id,rt<<1|1,mid+1,r,L,R);
    	return res;
    }
    
    int main()
    {
    	//freopen("in.txt","r",stdin);
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d%d",&n,&m);
    		for(int i=0;i<n;++i) scanf("%d",a+i);
    		for(int i=0;i<4;++i)
    			build(i,1,0,n-1);
    		int o,b,c;
    		while(m--)
    		{
    			scanf("%s",com);
    			if(com[0]=='S'){
    				scanf("%d%d",&b,&c);
    				int ans=0;
    				for(int i=0;i<4;++i){
    					ans+=query(i,1,0,n-1,b,c)*(1<<i);
    				}
    				printf("%d
    ",ans);
    			}else{
    				scanf("%d%d%d",&o,&b,&c);
    				if(com[0]=='X'){
    					for(int i=0;i<4;++i) if(o&(1<<i))
    						update(i,1,0,n-1,b,c,2);
    				}else if(com[0]=='O'){
    					for(int i=0;i<4;++i) if(o&(1<<i))
    						update(i,1,0,n-1,b,c,1);
    				}else if(com[0]=='A'){
    					for(int i=0;i<4;++i) if(!(o&(1<<i)))
    						update(i,1,0,n-1,b,c,0);
    				}
    			}
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    深入理解计算机系统 第六章 存储器层次结构 第二遍
    深入理解计算机系统 第六章 存储器层次结构
    深入理解计算机系统 第八章 异常控制流 Part2 第二遍
    深入理解计算机系统 第八章 异常控制流 part2
    深入理解计算机系统 第八章 异常控制流 Part1 第二遍
    深入理解计算机系统 第八章 异常控制流 part1
    深入理解计算机系统 第三章 程序的机器级表示 Part2 第二遍
    深入理解计算机系统 第三章 程序的机器级表示 part2
    深入理解计算机系统 第三章 程序的机器级表示 Part1 第二遍
    深入理解计算机系统 第三章 程序的机器级表示 part1
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5552416.html
Copyright © 2011-2022 走看看