HDU-1698 Just a Hook(线段树区间更新)

题目描述

在 DotA 的游戏中,Pudge 的肉钩实际上是大多数英雄最可怕的东西。挂钩由几个长度相同的连续金属棒组成。现在 Pudge 想在钩子上做一些操作。

让我们将钩子的连续金属棒从 1 到 N 编号。对于每次操作,Pudge 可以将编号从 X 到 Y的连续金属杆更改为铜棒、银棒或金棒。

钩子的总值计算为 N 根金属棒的值之和。更准确地说,每种棍子的值计算如下:

对于每个铜棒,其值为 1。

对于每个银棒,其值为 2。

对于每根金棒,其值为 3。

Pudge想知道执行操作后钩子的总值。你会认为原来的钩子是由铜棒制成的。

输入格式

输入由几个测试用例组成。输入的第一行是案例的数量。样例不超过 10 例。

对于每种情况,第一行包含整数 N ( 1 ≤ N ≤ 100000 ) N(1 \leq N \leq 100000) N(1N100000),这是 Pudge 肉钩的棒数,第二行包含整数 Q ( 0 ≤ Q ≤ 10000 ) Q(0 \leq Q \leq 10000) Q(0Q10000),这是操作数。

接下来的 Q 行,每行包含三个整数 X 、 Y ( 1 ≤ X ≤ Y ≤ N ) , Z ( 1 ≤ Z ≤ 3 ) X、Y(1 \leq X \leq Y \leq N),Z(1 \leq Z \leq 3) XY(1XYN)Z(1Z3)

定义了一个操作:将从 X 到 Y 编号的棒更改为金属类 Z,其中 Z=1 表示铜类,Z=2 表示银类,Z=3 表示金类。

输出格式

对于每种情况,在一行中打印一个数字,表示操作后钩子的总值。

样例输入

1
10
2
1 5 2
5 9 3

样例输出

Case 1: The total value of the hook is 24.

提交链接

https://acm.hdu.edu.cn/showproblem.php?pid=1698

提示

样例解释:
一组样例,10 根金属棒,两次操作。初始的时候每一个数为 1。
1 5 2,把区间 [1,5] 每个数改为 2,更改后区间为: 2 2 2 2 2 1 1 1 1 1
5 9 3,把区间 [5,9] 每个数改为 3,更改后区间为:2 2 2 2 3 3 3 3 3 1
结束后整根棒子的总和为 24

解析

建树,区间更新,标记下传

参考代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 9;
ll sum[maxn << 2] , add[maxn << 2];
int n , q , t;
void build(int l , int r , int k)
{
	if(l == r)
	{
		sum[k] = 1;
		return;
	}
	int mid = (l + r) >> 1;
	build(l , mid , k << 1);
	build(mid + 1 , r , k << 1 | 1);
	sum[k] = sum[k << 1] + sum[k << 1 | 1];
}
void Add(int value , int l , int r ,int k)
{
	add[k] = value;
	sum[k] = value * (r - l + 1); 
}
void pushdown(int value , int l , int mid , int r , int k)
{
	if(add[k] == 0)
		return;
	Add(add[k] , l , mid , k << 1);
	Add(add[k] , mid + 1 , r , k << 1 | 1);
	add[k] = 0;
}
void update(int x , int y ,int value , int l , int r , int k)
{
	if(x <= l && y >= r)
	{
		Add(value , l , r , k);
		return;
	}
	int mid = (l + r) >> 1;
	pushdown(value , l , mid , r , k);	
	if(x <= mid)
		update(x , y , value , l , mid , k << 1);
	if(y > mid)
		update(x , y , value , mid + 1 , r , k << 1 | 1);
	sum[k] = sum[k << 1] + sum[k << 1 | 1];
}
int main()
{
	scanf("%d" , &t);
	for(int tot = 1; tot <= t; tot++)
	{
		memset(sum , 0 , sizeof(sum));
		memset(add , 0 , sizeof(add));
		scanf("%d%d" , &n , &q);
		build(1 , n , 1);
		while(q--)
		{
			int x , y , value;
			scanf("%d%d%d" , &x , &y , &value);
			update(x , y , value , 1 , n , 1);
		}
		printf("Case %d: The total value of the hook is %lld.\n" , tot ,sum[1]);
		
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zaiyang遇见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值