HDU 1698(线段树 区域更新,区域求值)

本文介绍了一种使用延迟标记实现的区间更新与查询算法。通过在更新时不立即更改所有相关节点,而是采用标记来延迟更新操作,可以显著提高效率。文章详细解释了PushDown和PushUp等关键函数的作用,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:点击打开链接

//区域更新 区域查询
//需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候
//PushDown()需要认真想明白;
//大体意思是:
//每次查询到(L,R)大于(l,r)的区间,先把此段更新(或是替换原来的col),然后回溯,更新(PushUp)父节点们
//不先去管子节点们,反正已经此段标记过了
//当查询到的段不为 (L,R)大于(l,r)的区间,就要考虑当前段->是否之前更新的还未传给子节点(此段col不为零说明未传给子节点)
//需要PushDown()一下(记得取消此段的col标记),让子节点成为之前应变成但未变成的样子,再去处理子节点
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define MAXN 100005
int setTree[MAXN<<2];
int col[MAXN<<2];
void PushUp(int root){
	setTree[root]=setTree[root<<1]+setTree[root<<1|1];
}
void PushDown(int root,int wideth){
	if(col[root]){
		col[root<<1]=col[root<<1|1]=col[root];
		setTree[root<<1]=col[root]*(wideth-(wideth>>1));
		setTree[root<<1|1]=col[root]*(wideth>>1);
		col[root]=0;
	}
}
void Build(int l,int r,int root){
	col[root]=0;
	if(l==r){
		setTree[root]=1;
		return;
	}
	int m=(l+r)>>1;
	Build(l,m,root<<1);
	Build(m+1,r,root<<1|1);
	PushUp(root);
}
void Update(int L,int R,int key,int l,int r,int root){//区域更新最关键也是最难理解的地方
	if(L<=l&&R>=r){
		setTree[root]=((r-l)+1)*key;
		col[root]=key;
		return;
	}
	PushDown(root,r-l+1);
	int m=(l+r)>>1;
	if(L<=m)
	   Update(L,R,key,l,m,root<<1);
	if(R>m)
	   Update(L,R,key,m+1,r,root<<1|1);
	PushUp(root);
}
int main(){
	int t,m,n;
	int x,y,z;
	cin>>t;
	for(int i=1;i<=t;i++){
		cin>>n>>m;
		Build(1,n,1);
		for(int j=1;j<=m;j++){
			scanf("%d%d%d",&x,&y,&z);
			Update(x,y,z,1,n,1);
		}
		printf("Case %d: The total value of the hook is %d.\n",i,setTree[1]);
	}
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值