Just a Hook(线段树)

Just a Hook(线段树)

Time limit:2000 ms
Memory limit:32768 kB
OS:Windows
judge:https://vjudge.net/contest/295911#problem/E

描述

In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of the same length.

在这里插入图片描述

Now Pudge wants to do some operations on the hook.

Let us number the consecutive metallic sticks of the hook from 1 to N. For each operation, Pudge can change the consecutive metallic sticks, numbered from X to Y, into cupreous sticks, silver sticks or golden sticks.
The total value of the hook is calculated as the sum of values of N metallic sticks. More precisely, the value for each kind of stick is calculated as follows:

For each cupreous stick, the value is 1.
For each silver stick, the value is 2.
For each golden stick, the value is 3.

Pudge wants to know the total value of the hook after performing the operations.
You may consider the original hook is made up of cupreous sticks.

Input

The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 10 cases.
For each case, the first line contains an integer N, 1<=N<=100,000, which is the number of the sticks of Pudge’s meat hook and the second line contains an integer Q, 0<=Q<=100,000, which is the number of the operations.
Next Q lines, each line contains three integers X, Y, 1<=X<=Y<=N, Z, 1<=Z<=3, which defines an operation: change the sticks numbered from X to Y into the metal kind Z, where Z=1 represents the cupreous kind, Z=2 represents the silver kind and Z=3 represents the golden kind.

Output

For each case, print a number in a line representing the total value of the hook after the operations. Use the format in the example.

Sample Input

1
10
2
1 5 2
5 9 3

Sample Output

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

题意

在DATA的游戏中,普吉的钩实际上是大多数英雄最可怕的东西。钩子由几个长度相同的连续金属棒组成。

现在,普吉想在钩子上做一些操作。

让我们把钩子的连续金属棒从1个编号到N个。每次操作时,Pudge都可以将连续金属棒从X到Y,变成铜棒、银棒或金棒。

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

对于每个铜棒,值为1。

对于每个银棒,值为2。

每根金棒的价值是3。

Pudge希望在执行操作后知道钩子的总值。

你可以认为原来的钩子是由铜棒组成的。

输入

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

对于每种情况,第一行包含一个整数n,1<=n<=100000,这是Pudge的钩的条数,第二行包含一个整数q,0<=q<=100000,这是操作数。

接下来的q行,每行包含三个整数x,y,1<=x<=y<=n,z,1<=z<=3,这定义了一个操作:将编号为x到y的木棒改为金属类z,其中z=1代表铜类,z=2代表银类,z=3代表金类。

输出

对于每种情况,在一行中打印一个数字,表示操作后挂钩的总值。使用示例中的格式。

思路

简单线段树,需要加优化节省时间

把当前node值作为整个区间所有元素的值

更新节点时若当前区间正是目标区间,则把当前node节点值改为目标值;若不是说明更新完所有点后当前区间的所有元素没有一个统一的值,这时只需把当前区间的node节点值变为0,然后继续深入查找即可!

查询时如果当前node节点的值不为0说明当前区间所有元素有一个统一的值:当前node节点值,然后把当前node节点值归零;如果当前node节点值为0则说明当前区间所有元素没有一个统一的值。需要进一步深入查找

代码

#include <iostream>
#include <algorithm>
#define maxn 100000
#define _for(i, a) for(int i = 0; i < (a); i++)
#define _rep(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;
int a[maxn * 4], sum;
void build(int node, int beg, int end) {
	a[node] = 1;
}
void upd(int node, int beg, int end, int l, int r, int val) {
	if (beg == l && end == r) {
		a[node] = val;
		return;
	}
	if (a[node]) {
		a[node * 2] = a[node * 2 + 1] = a[node];
		a[node] = 0;
	}
	int mid = (beg + end) / 2;
	if (mid >= r) upd(node * 2, beg, mid, l, r, val);
	else if (mid < l) upd(node * 2 + 1, mid + 1, end, l, r, val);
	else {
		upd(node * 2, beg, mid, l, mid, val);
		upd(node * 2 + 1, mid + 1, end, mid + 1, r, val);
	}
}
void query(int node, int beg, int end) {
	if (a[node]) {
		sum += a[node] * (end - beg + 1);
		return;
	}
	int mid = (beg + end) / 2;
	query(node * 2, beg, mid);
	query(node * 2 + 1, mid + 1, end);
}

int main() {
	//freopen("in.txt", "r", stdin);
	int T;
	scanf("%d", &T);
	_rep(q, 1, T) {
		sum = 0;
		int N, Q;
		scanf("%d%d", &N, &Q);
		build(1, 1, N);
		int x, y, z;
		_for(i, Q) {
			scanf("%d%d%d", &x, &y, &z);
			upd(1, 1, N, x, y, z);
		}
		query(1, 1, N);
		printf("Case %d: The total value of the hook is %d.\n", q, sum);
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值