Just a Hook:线段树+区间修改

E - Just a Hook

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.

题目描述:t组数据,输入n,q,从1~n初值为1,q次修改操作,求最后的所有值的和,都写在代码里了,

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm> 
using namespace std;
const int maxn = 100010;
int T, n, k, l, r, v, lazy[maxn * 4];

struct node {	
	int l, r, value;											// value代表是区间和
}t[maxn * 4];

void pushup(int p) {
	t[p].value = t[p << 1].value + t[p << 1 | 1].value;			//节点更新
}

void built(int p, int l, int r) {								// p当前节点  l区间左值  r区间右值
	t[p].l = l;
	t[p].r = r;
	if (l == r) {
		t[p].value = 1;											//按照题目要求 初始值为1
		return;
	}
	int mid = l + r >> 1;
	built(p << 1, l, mid);										//建左儿子
	built(p << 1 | 1, mid + 1, r);								//建右儿子
	pushup(p);													//更新当前节点
}

void pushdown(int p, int l, int r) {							// p当前节点  l区间左值  r区间右值
	if (lazy[p]) {
		int mid = l + r >> 1;
		lazy[p << 1] = lazy[p << 1 | 1] = lazy[p];				//给儿子打上标记 
		t[p << 1].value = (mid - l + 1)*lazy[p];				//更新左儿子 
		t[p << 1 | 1].value = (r - mid)*lazy[p];				//更新右儿子 
		lazy[p] = 0;											//去掉当前点标记 
	}
}

void update(int p, int l, int r, int v) {						//p当前节点 l修改区间的左值 r修改区间的右值 v修改数值
	if (l <= t[p].l&&t[p].r <= r) {
		lazy[p] = v;											//打上标记,不用继续向下走了
		t[p].value = v*(t[p].r - t[p].l + 1);					//注意当前节点的value 当前节点下有(t[p].r - t[p].l + 1)个叶子,
																//每个叶子都要变成v,所以当前节点就是(叶子数)*v
		return;
	}
	pushdown(p, t[p].l, t[p].r);								//不满足,向下一层打标记
	int mid = t[p].l + t[p].r >> 1;
	if (l <= mid)update(p << 1, l, r, v);						//更新左儿子
	if (r>mid)update(p << 1 | 1, l, r, v);						//更新右儿子
	pushup(p);
}

int main() {
	scanf("%d", &T);
	for (int i = 1; i <= T; i++) {
		memset(lazy, 0, sizeof(lazy));							//不要忘记初始化!!!

		scanf("%d%d", &n, &k);
		built(1, 1, n);
		while (k--) {
			scanf("%d%d%d", &l, &r, &v);
			update(1, l, r, v);
		}
		printf("Case %d: The total value of the hook is %d.
", i, t[1].value);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/52dxer/p/10547799.html