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;
    }
    

      

  • 相关阅读:
    可爱的中国电信 请问我们的电脑还属于我们自己吗?
    了解客户的需求,写出的代码或许才是最优秀的............
    DELPHI DATASNAP 入门操作(3)简单的主从表的简单更新【含简单事务处理】
    用数组公式获取字符在字符串中最后出现的位置
    在ehlib的DBGridEh控件中使用过滤功能(可以不用 MemTableEh 控件 适用ehlib 5.2 ehlib 5.3)
    格式化json返回的时间
    ExtJs中使用Ajax赋值给全局变量异常解决方案
    java compiler level does not match the version of the installed java project facet (转)
    收集的资料(六)ASP.NET编程中的十大技巧
    收集的资料共享出来(五)Asp.Net 权限解决办法
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5552416.html
Copyright © 2011-2022 走看看