hihoCoder#1080 (线段树)

题目大意:线段树的区间更改与查询,但是涉及到两种区间修改方式,一是给区间中的数全部加上一个数,二是将一个区间全部置为同一个数,然后询问整个区间和。

题目分析:处理好set操作和add操作的先后顺序就OK了。

 

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=100001;

int n,m;
int tr[N*4+5];
int lazy_set[N*4+5];
int lazy_add[N*4+5];

void pushDown(int rt,int l,int r)
{
	int mid=l+(r-l)/2;
	if(lazy_set[rt]!=0){
		lazy_set[rt<<1]=lazy_set[rt<<1|1]=lazy_set[rt];
		lazy_add[rt<<1]=lazy_add[rt<<1|1]=0;
		tr[rt<<1]=lazy_set[rt]*(mid-l+1);
		tr[rt<<1|1]=lazy_set[rt]*(r-mid);
		lazy_set[rt]=0;
	}
	if(lazy_add[rt]!=0){
		lazy_add[rt<<1]+=lazy_add[rt];
		lazy_add[rt<<1|1]+=lazy_add[rt];
		tr[rt<<1]+=lazy_add[rt]*(mid-l+1);
		tr[rt<<1|1]+=lazy_add[rt]*(r-mid);
		lazy_add[rt]=0;
	}
}

void makeTree(int rt,int l,int r)
{
	if(l==r){
		scanf("%d",&tr[rt]);
	}else{
		int mid=l+(r-l)/2;
		makeTree(rt<<1,l,mid);
		makeTree(rt<<1|1,mid+1,r);
		tr[rt]=tr[rt<<1]+tr[rt<<1|1];
	}
}

void update(int rt,int l,int r,int L,int R,int x,int flag)
{
	if(L<=l&&r<=R){
		if(flag){
			lazy_set[rt]=x;
			lazy_add[rt]=0;
			tr[rt]=x*(r-l+1);
		}else{
			lazy_add[rt]+=x;
			tr[rt]+=x*(r-l+1);
		}
	}else{
		pushDown(rt,l,r);
		int mid=l+(r-l)/2;
		if(L<=mid)
			update(rt<<1,l,mid,L,R,x,flag);
		if(R>mid)
			update(rt<<1|1,mid+1,r,L,R,x,flag);
		tr[rt]=tr[rt<<1]+tr[rt<<1|1];
	}
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		memset(lazy_set,0,sizeof(lazy_set));
		memset(lazy_add,0,sizeof(lazy_add));
		makeTree(1,0,n);
		int flag,l,r,v;
		while(m--)
		{
			scanf("%d%d%d%d",&flag,&l,&r,&v);
			update(1,0,n,l,r,v,flag);
			printf("%d\n",tr[1]);
		}
	}
	return 0;
}

  

posted @ 2016-05-16 11:05  20143605  阅读(160)  评论(0编辑  收藏  举报