线段树专题#4_蒟蒻训练历程记录_HDU1698_ 延迟标记、区间更新

              这道题如果第一次碰到这种类型的,大概会T,然后就要学习一种神奇的延迟标记的方法。通过这种标记在当前范围在有效查询区间内才将进行更新,这样可以避免一直更新到叶子结点,防止代码超时,膜ORZ。。。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<stack>//线段树区间更新,延迟标记 
using namespace std;
typedef long long ll;
#define N 100010
int g[4*N];
int mk[4*N];//延迟标记,0表示没有标记,否则以更新的价值作为标记 

void init(int rt, int l, int r)
{
	mk[rt] = 0; 
	if(l == r)
	{
		g[rt] = 1;
		return;
	}
	int mid = (l+r)>>1;
	init(rt<<1, l, mid);
	init(rt<<1|1, mid+1, r);
}

void PushUp(int rt)//向上更新 
{
	g[rt] = g[rt<<1]+g[rt<<1|1];
}

void PushDown(int rt, int m)//对某一个区间进行改变,如果被标记了,在查询的时候就得把改变传给子节点,因为查询的并不一定是当前区间
{
	if(mk[rt])//已经被标记过,该区间被改变过
	{
	   mk[rt<<1] = mk[rt<<1|1] = mk[rt];
	   g[rt<<1] = (m-(m>>1))*mk[rt];
	   g[rt<<1|1] = (m>>1)*mk[rt];
	   mk[rt] = 0; 
    }
}

void Update(int rt, int l, int r, int L, int R, int k)
{
	if(l >= L && r <= R)
	{
		mk[rt] = k;
		g[rt] = k*(r-l+1);
		return;//mdzzORZ 
		//printf("l:%d r:%d g[rt]:%d\n", l, r, g[rt]);
	}
	PushDown(rt, r-l+1);//向下传递 
	int mid = (l+r)>>1;
	if(mid >= L)
	{
		Update(rt<<1, l, mid, L, R, k);
	}
	if(mid < R)
	{
		Update(rt<<1|1, mid+1, r, L, R, k);
	}
	//printf("l:%d r:%d g[rt]:%d\n", l, r, k1+k2);
	PushUp(rt);
}

int main()
{
	int t, num = 0;
	scanf("%d", &t);
	while(t--)
	{
		int n, m;
		scanf("%d%d", &n, &m);
		init(1, 1, n);
		while(m--)
		{
			int l, r, k;
			scanf("%d%d%d", &l, &r, &k);
			Update(1, 1, n, l, r, k);
			//PushUp(1, 1, n);
		}
		printf("Case %d: The total value of the hook is %d.\n", ++num, g[1]);
	} 
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值