HDU 1698 线段树(区间修改)

第一行给出样例个数;

第二行给出hook的个数(全部初始化为1)

第三行给出区间操作的个数

接下来每一行有x,y,z;代表在 \left [ x,y \right ] 区间内的所有hook的数值都改成z.

最后,求出来这些操作之后,所有hook的总和。


//AC
//HDU 1698 线段树(区间查询和修改)
//只要求查询总和 --- tree[1] 
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<set>
#include<queue>
#include<stack> 
using namespace std;
const int maxn=1e5+5;
int num[maxn];
int tree[maxn<<2];
int mark[maxn<<2];

void pushup(int root)
{
	tree[root]=tree[2*root]+tree[2*root+1];
	return;
}


void pushdown(int root,int ln,int rn)
{
	if(mark[root])
	{
		tree[2*root]=ln*mark[root];//为什么之前传了value不对呢?应该是mark[]不一定对应当前的value 
		tree[2*root+1]=rn*mark[root];
		mark[2*root]=mark[root];
		mark[2*root+1]=mark[root];
		mark[root]=0;
	}
	return;
}

void build(int root,int left,int right)
{
	mark[root]=0;
	if(left==right)
	{
		tree[root]=num[left];
		return;
	}
	int mid=(left+right)/2;
	build(2*root,left,mid);
	build(2*root+1,mid+1,right);
	pushup(root);
}

void Update(int root,int uleft,int uright,int left,int right,int value)
{
	if(left>uright || right<uleft)//没有交集 
		return;
	if(left>=uleft && right<=uright)//更新后要做的正经事2333,easy to forget 
	{								//如果在区间内 
		tree[root]=value*(right-left+1);
		mark[root]=value;
		return;
	 } 
	int mid=(left+right)/2;
	
	pushdown(root,mid-left+1,right-mid);
	
	if(uleft<=mid)
		Update(2*root,uleft,uright,left,mid,value);
	if(mid<uright)
		Update(2*root+1,uleft,uright,mid+1,right,value);
	pushup(root);
 } 



int main()
{
	int tcase;
	scanf("%d",&tcase);
	int tc=1;
	while(tcase--)
	{
		int n,q;
		scanf("%d%d",&n,&q); 
		
		for(int i=1;i<=n;i++)
			num[i]=1;
		build(1,1,n);
		
//		for(int i=1;i<=4*n;i++)
//		cout<<tree[i]<<" ";
//		cout<<endl;
		
		while(q--)
		{
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			Update(1,x,y,1,n,z);
			
			for(int i=1;i<=4*n;i++)
				cout<<tree[i]<<" ";
			cout<<endl;
		}
		printf("Case %d: The total value of the hook is %d.\n",tc++,tree[1]);
	}
 } 
 

注意pushdown()函数的操作。在下推的过程,不能赋值value的。

很有可能,本来应该下推的,但是由于并不需要更新,就搁置了。如果你用当前的value去更新,可能跟上一次的数值不一样嘛。

是这样理解的不????

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值