hihoCoder #1078 : 线段树的区间修改

题目大意及分析:

线段树成段更新裸题。

代码如下:

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

const int N=100000;

int n,m;
int a[N+5];
int tr[N*4+5];
int lazy[N*4+5];

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

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)
{
	if(L<=l&&r<=R){
		lazy[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);
		if(R>mid)
			update(rt<<1|1,mid+1,r,L,R,x);
		tr[rt]=tr[rt<<1]+tr[rt<<1|1];
	}
}

int query(int rt,int l,int r,int L,int R)
{
	if(L<=l&&r<=R)
		return tr[rt];
	pushDown(rt,l,r);
	int res=0;
	int mid=l+(r-l)/2;
	if(L<=mid)
		res+=query(rt<<1,l,mid,L,R);
	if(R>mid)
		res+=query(rt<<1|1,mid+1,r,L,R);
	return res;
}

int main()
{
	while(~scanf("%d",&n))
	{
		memset(tr,0,sizeof(tr));
		memset(lazy,-1,sizeof(lazy));
		makeTree(1,1,n);
		scanf("%d",&m);
		int flag,a,b,c;
		while(m--)
		{
			scanf("%d",&flag);
			if(flag){
				scanf("%d%d%d",&a,&b,&c);
				update(1,1,n,a,b,c);
			}else{
				scanf("%d%d",&a,&b);
				printf("%d
",query(1,1,n,a,b));
			}
		}
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/5467425.html