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

题目传送:Just a Hook

思路:线段树,成段替换, 区间求和。成段更新时,注意延迟标记的作用,它就是用来暂停往下更新来达到节省时间的,然后每次更新每个节点的子节点之前都要判断是否需要往下更新。

AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <cctype>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 100005;

int sum[maxn << 2];//求区间和
int lazy[maxn << 2];//延迟标记 

void pushdown(int rt, int m) {
	if(lazy[rt]) {//如果之前这里做了标记,则说明没有往下更新,暂停了一下,用来判断是否需要往下更新
		lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt];
		sum[rt << 1] = (m - (m >> 1)) * lazy[rt];
		sum[rt << 1 | 1] = (m >> 1) * lazy[rt];
		lazy[rt] = 0;//往下更新完后,标记置为0,即当前不需要往下更新
	}
}

void build(int l, int r, int rt) {
	lazy[rt] = 0;
	sum[rt] = r - l + 1;
	if(l == r) return;
	int mid = (l + r) >> 1;
	build(l, mid, rt << 1);
	build(mid + 1, r, rt << 1 | 1);
}

void update(int L, int R, int c, int l, int r, int rt) {
	if(L <= l && r <= R) {
		sum[rt] = c * (r - l + 1);
		lazy[rt] = c;//延迟标记,每次把该段更新完后暂时不往下更新,节省时间
		return;
	}
	pushdown(rt, r - l + 1);//向下更新
	int mid = (l + r) >> 1;
	if(L <= mid) update(L, R, c, l, mid, rt << 1);
	if(R >= mid + 1) update(L, R, c, mid + 1, r, rt << 1 | 1);
	sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];//向上更新
}

int main() {
	int T, n, m;
	scanf("%d", &T);
	for(int cas = 1; cas <= T; cas ++) {
		scanf("%d %d", &n, &m);
		build(1, n, 1);

		for(int i = 0; i < m; i ++) {
			int a, b, c;
			scanf("%d %d %d", &a, &b, &c);
			update(a, b, c, 1, n, 1);
		}

		printf("Case %d: The total value of the hook is %d.\n", cas, sum[1]);
	}
	return 0;
}
时间: 2024-09-03 15:15:38

HDU - 1698 - Just a Hook (线段树-成段更新)的相关文章

HDU 1698 Just a Hook (线段树 成段更新 lazy-tag思想)

题目链接 题意: n个挂钩,q次询问,每个挂钩可能的值为1 2 3,  初始值为1,每次询问 把从x到Y区间内的值改变为z.求最后的总的值. 分析:用val记录这一个区间的值,val == -1表示这个区间值不统一,而且已经向下更新了, val != -1表示这个区间值统一, 更新某个区间的时候只需要把这个区间分为几个区间更新就行了, 也就是只更新到需要更新的区间,不用向下更新每一个一直到底了,在更新的过程中如果遇到之前没有向下更新的, 就需要向下更新了,因为这个区间的值已经不统一了. 其实这就

hdu 1698 Just a Hook 线段树成段更新

线段树功能:update:成段替换 成段更新去要用到延迟标记,具体调试代码就容易懂些 #include <iostream> #include <string> #include <cstdio> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; const int MAXN = 111111; int sum[MAXN<<2], ch

HDU1698_Just a Hook(线段树/成段更新)

解题报告 题意: 原本区间1到n都是1,区间成段改变成一个值,求最后区间1到n的和. 思路: 线段树成段更新,区间去和. #include <iostream> #include <cstdio> #include <cstring> using namespace std; int sum[500000],lz[500000]; void push_up(int root,int l,int r) { sum[root]=sum[root*2]+sum[root*2+

hdu1698Just a Hook 线段树 成段更新水题

//简单的线段树,注意成段更新,以免超时 #include<iostream> #include<cstdio> #include<cstring> using namespace std ; const int maxn = 100010 ; struct node { int value ; int r , l; int flag ;//记录到当前区间的状态 }tree[maxn<<2] ; void build(int l , int r ,int v

HDU 3397 Sequence operation(线段树&#183;成段更新&#183;区间合并&#183;混合操作)

题意  给你一个只有0, 1的数组  有这些操作 0. 将[a, b]区间的所有数都改为0 1. 将[a, b]区间的所有数都改为1 2. 将[a, b]区间的所有数都取反 即与1异或 3. 输出区间[a, b]中1的个数  即所有数的和 4. 输出区间[a, b]中最大连续1的长度 对于所有的3, 4操作输出对应的答案 单个的操作都很简单  但搞在一起就有点恶心了  还好数组里的数只有0和1 线段树维护9个值 对应区间0, 1的最大长度len[i]  对应区间左端点为起点的最大0, 1长度ll

线段树(成段更新) HDU 1698 Just a Hook

题目传送门 1 /* 2 线段树-成段更新:第一题!只要更新区间,输出总长度就行了 3 虽然是超级裸题,但是用自己的风格写出来,还是很开心的:) 4 */ 5 #include <cstdio> 6 #include <algorithm> 7 #include <cmath> 8 #include <cstring> 9 #include <string> 10 #include <iostream> 11 using namesp

线段树成段更新 hdu 1698 Just a Hook

题意:给出n根金属棒,和操作数q,初始时每个金属棒价值都为1,每次操作可以把从x到y的金属棒更换材质,铜为1,银为2,金为3,最后统计所有的金属棒总价值是多少. 线段树成段更新,需要用到lazy标记,所谓lazy标记就是:更新一个区间的时候不更新到底,只更新到第一个满足更新范围的区间(即范围内的最大的区间),然后给节点加上lazy标记,以后需要更新到该节点的子节点的时候,就把lazy标记转移到子节点上,这样大大提升了效率. 代码:

HDU 1698 Just a Hook(线段树区间替换)

题目地址:HDU 1698 区间替换裸题.同样利用lazy延迟标记数组,这里只是当lazy下放的时候把下面的lazy也全部改成lazy就好了. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #in

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

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17214    Accepted Submission(s): 8600 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f

HDU 1698 Just a Hook 线段树解法

很经典的题目,而且是标准的线段树增加lazy标志的入门题目. 做了好久线段树,果然是practice makes perfect, 这次很畅快,打完一次性AC了. 标志的线段树函数. 主要是: 更新的时候只更新到需要的节点,然后最后的时候一次性把所以节点都更新完毕. 这也是线段树常用的技术. #include <stdio.h> const int SIZE = 100005; struct Node { bool lazy; int metal; }; const int TREESIZE