FZU 2105 Digits Count

链接:点击打开链接

          四个操作,或,与,异或,求和。成段更新。

      如果相邻两个数经过操作之后变成相同的数了,那么再经过覆盖了该区间的操作时,那么他们的值将同时发生改变,变成另外一个相同的值,这多次操作下去,之后将生更多的相同的数字区间,这里的相同数字就是懒惰标记更新的关键:例如:OR 6 0 3, A=[6 6 6 7];    其中6出现了3次

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 1000010
struct node{
	int l;
	int r;
	int cover;
	}anode[N*4];
int data[N];
void pushdown(int n){
	if(anode[n].cover!=-1){
		//anode[n].sum=anode[n].cover*(anode[n].r-anode[n].l+1);
		anode[2*n].cover=anode[2*n+1].cover=anode[n].cover;
		anode[n].cover=-1;
		return;
		}
	}
void pushup(int n){
	if(anode[2*n].cover==anode[2*n+1].cover&&anode[2*n].cover!=-1)
		 anode[n].cover=anode[2*n].cover;
	}		
void bulid(int l,int r,int n){
	int mid;
	mid=(l+r)>>1;
	anode[n].l=l;
	anode[n].r=r;
	anode[n].cover=-1;
    if(l==r){
		anode[n].cover=data[l];
		return;
		}
	    bulid(l,mid,2*n);
	    bulid(mid+1,r,2*n+1);
    	if(anode[2*n].cover==anode[2*n+1].cover&&anode[n].cover!=-1)
		 anode[n].cover=anode[2*n].cover;
	}
void updateAND(int l,int r,int n,int c){
	int mid;
	if(anode[n].l==l&&anode[n].r==r&&anode[n].cover!=-1){
		anode[n].cover&=c; 
		//printf("%d\n",anode[n].cover);
		return;
		}	
	  pushdown(n);
	  mid=(anode[n].l+anode[n].r)>>1;
	   if(r<=mid)
	   updateAND(l,r,2*n,c);
	   else if(l>mid)
	   updateAND(l,r,2*n+1,c);
	   else{
			updateAND(l,mid,2*n,c);
			updateAND(mid+1,r,2*n+1,c); 
			}
	   pushup(n);			
	}
void updateXOR(int l,int r,int n,int c){
	int mid;
	if(anode[n].l==l&&anode[n].r==r&&anode[n].cover!=-1){
		anode[n].cover^=c;
		//printf("%d\n",anode[n].cover);
		return;
		}	
	  pushdown(n);
	  mid=(anode[n].l+anode[n].r)>>1;
	   if(r<=mid)
	   updateXOR(l,r,2*n,c);
	   else if(l>mid)
	   updateXOR(l,r,2*n+1,c);
	   else{
			updateXOR(l,mid,2*n,c);
			updateXOR(mid+1,r,2*n+1,c); 
			}	
		pushup(n);		
	}
void updateOR(int l,int r,int n,int c){
	int mid;
	if(anode[n].l==l&&anode[n].r==r&&anode[n].cover!=-1){
		anode[n].cover|=c;
	//	printf("%d\n",anode[n].cover);
		return;
		}	
	  pushdown(n);
	  mid=(anode[n].l+anode[n].r)>>1;
	   if(r<=mid)
	   updateOR(l,r,2*n,c);
	   else if(l>mid)
	   updateOR(l,r,2*n+1,c);
	   else{
			updateOR(l,mid,2*n,c);
			updateOR(mid+1,r,2*n+1,c); 
			}
	   pushup(n);
	}			
int query(int l,int r,int n){
	int mid;
	mid=(anode[n].l+anode[n].r)>>1;
	if(anode[n].l==l&&anode[n].r==r&&anode[n].cover!=-1)
	return anode[n].cover*(anode[n].r-anode[n].l+1);
	pushdown(n);
	if(r<=mid)
	return query(l,r,2*n);
	else if(l>mid)
	return query(l,r,2*n+1);
	else return query(l,mid,2*n)+query(mid+1,r,2*n+1);
	pushup(n);
	}	

int main(){
	int t,n,m,a,b,c,i;
	char str[10];
	scanf("%d",&t);
	while(t--){
		scanf("%d %d",&n,&m);
		for(i=1;i<=n;i++)
		scanf("%d",&data[i]);
		bulid(1,n,1);
		//for(i=1;i<=7;i++)
		//printf("%d ",anode[i].sum);
		//for(i=1;i<=7;i++)
		//printf("%d ",anode[i].cover);
		while(m--){
			scanf("%s",str);
			if(!strcmp(str,"SUM")){
				scanf("%d %d",&a,&b);
			int	ans=query(a+1,b+1,1);
				printf("%d\n",ans);
				}
			else if(!strcmp(str,"XOR")){
				scanf("%d %d %d",&c,&a,&b);
				updateXOR(a+1,b+1,1,c);
				}
			else if(!strcmp(str,"OR")){
				scanf("%d %d %d",&c,&a,&b);
				updateOR(a+1,b+1,1,c);
				}
			else if(!strcmp(str,"AND")){
				scanf("%d %d %d",&c,&a,&b);
				updateAND(a+1,b+1,1,c);
				}		
			}
		}
		return 0;
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值