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): 18384    Accepted Submission(s): 9217

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.

Source

2008 “Sunline Cup” National Invitational Contest

Recommend

wangye   |   We have carefully selected several similar problems for you:  1542 1255 1828 1540 2871

题意:

给你一个区间1~n,刚开始全为1,之后进行Q个操作,每个操作给出x,y,z,表示将区间[x,y]所有的数改为z。Q操作后求区间所有数的和。

题解:简单线段树,更新Q次,查询一次,懒惰标记。

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<map>

#define N 100010
#define Mod 10000007
#define lson l,mid,idx<<1
#define rson mid+1,r,idx<<1|1
typedef long long ll;

const int INF = 1000010;

using namespace std;

int add[N << 2], sum[N << 2];

void pushdown ( int idx, int m )
{
    if ( add[idx] )
    {
        add[idx << 1] = add[idx];
        add[idx << 1 | 1] = add[idx];
        sum[idx << 1] = ( m - ( m >> 1 ) ) * add[idx];
        sum[idx << 1 | 1] = ( m >> 1 ) * add[idx];
        add[idx] = 0;
    }
}

void build ( int l, int r, int idx )
{
    add[idx] = 0;
    if ( l == r )
    {
        sum[idx] = 1;///初始化为1
        return;
    }
    int mid = ( l + r ) >> 1;
    build ( lson );
    build ( rson );
    sum[idx] = sum[idx << 1] + sum[idx << 1 | 1];
}

void update ( int l, int r, int idx, int x, int y, int k )
{
    if ( x <= l && r <= y )
    {
        sum[idx] = ( r - l + 1 ) * k;
        add[idx] = k;
        return;
    }
    pushdown ( idx, r - l + 1 );
    int mid = ( l + r ) >> 1;
    if ( x <= mid )
        update ( lson, x, y, k );
    if ( y > mid )
        update ( rson, x, y, k );
    sum[idx] = sum[idx << 1] + sum[idx << 1 | 1];
}

int main()
{
    int t, n, m;
    while ( ~scanf ( "%d", &t ) )
    {
        for ( int i = 1; i <= t; i++ )
        {
            scanf ( "%d%d", &n, &m );
            build ( 1, n, 1 );
            int x, y, z;
            while ( m-- )
            {
                scanf ( "%d%d%d", &x, &y, &z );
                update ( 1, n, 1, x, y, z );
            }
            printf ( "Case %d: The total value of the hook is %d.\n", i, sum[1] );
        }
    }
    return 0;
}
时间: 2024-08-02 02:49: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

【POJ】3468 A Simple Problem with Integers ——线段树 成段更新 懒惰标记

A Simple Problem with Integers Time Limit:5000MS   Memory Limit:131072K Case Time Limit:2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each

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