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

题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1698

题目:

Problem Description

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.

思路:

懒惰标记法,延迟更新。没学过这个知识点的,可以先学习一下。网上有篇介绍该知识点的博客:http://blog.csdn.net/zip_fan/article/details/46775633

代码:

 1 #include <cstdio>
 2 const int N=4e5;
 3 struct node{
 4     int l,r;
 5     int lazy,sum;
 6 }tree[N];
 7 int n;
 8 void pushup(int i){//更新父节点
 9     tree[i].sum=tree[(i*2)+1].sum+tree[i*2].sum;
10 }
11 void pushdown(int i){//更新子节点
12     if(tree[i].lazy){
13         tree[2*i].lazy=tree[2*i+1].lazy=tree[i].lazy;//将子节点也懒惰标记
14         tree[2*i].sum=(tree[2*i].r-tree[2*i].l+1)*tree[2*i].lazy;//sum会等于长度值*标记值
15         tree[2*i+1].sum=(tree[2*i+1].r-tree[2*i+1].l+1)*tree[2*i+1].lazy;
16         tree[i].lazy=0;//更新完,取消该节点的标记
17     }
18 }
19 void build(int bg,int ed,int i){
20     if(i>4*n)   return;
21     tree[i].l=bg;
22     tree[i].r=ed;
23     tree[i].lazy=0;//多个测试样例,注意初始化
24     if (bg == ed)   tree[i].sum=1;
25     else{
26         int mid=(bg+ed)/2;
27         build(bg, mid, 2*i);
28         build(mid+1, ed, 2*i+1);
29         pushup(i);//回溯更新父节点
30
31     }
32 }
33 void update(int bg,int ed,int i,int v){
34     if(bg<=tree[i].l && tree[i].r<=ed){
35         tree[i].lazy=v;
36         tree[i].sum=(tree[i].r-tree[i].l+1)*v;
37         return ;
38     }
39     pushdown(i);//当用到该节点时,就向下更新
40     int mid=(tree[i].r+tree[i].l)/2;
41     if(ed<=mid) update(bg, ed, 2*i, v);//该区间完全在左子树
42     else if(bg>mid) update(bg, ed, 2*i+1, v);//该区间完全在右子树
43     else if(bg<=mid && ed>mid){//既在左子树又在右子树
44         update(bg, mid, 2*i, v);
45         update(mid+1, ed, 2*i+1, v);
46     }
47     pushup(i);//回溯更新父节点
48 }
49 int main(){
50     int t,m;
51     scanf("%d",&t);
52     for (int i=1; i<=t; i++) {
53         scanf("%d%d",&n,&m);
54         build(1, n, 1);
55         for (int j=0; j<m; j++) {
56             int x,y,v;
57             scanf("%d%d%d",&x,&y,&v);
58             update(x, y, 1, v);
59         }
60         printf("Case %d: The total value of the hook is %d.\n",i,tree[1].sum);
61     }
62     return 0;
63 }
时间: 2024-11-05 17:02:35

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