题目链接: 传送门

Minimum Inversion Number

Time Limit: 1000MS     Memory Limit: 32768 K

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 Iutput

1
10
2
1 5 2
5 9 3

Sample Output

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

解题思路

肯定不能用单点更新的办法来逐个更新一个区间,而正解的区间更新一开始也看得我云里雾里,最好的办法就是跟着程序走一遍,调试一遍。
懒惰标记是整个代码的核心,搞懂了懒惰标记也就理解了整个算法。懒惰标记实际上就是让叶子节点暂时处于不更新状态,用到的时候再更新,代码中我用col[]数组用来作为懒惰标记,假设区间总长度是1-10,我们现在想要更新1-6,(将1-6的值都加3)那么update()会先找1-10,发现不合适,再找他的左右孩子,发现1<5,说明1-6的区间在1-10的左孩子中,同时6>5,1-6也在1-10的右孩子中,这样依次去找1-6在的区间。但是找到1-5的时候,我们发现整个1-5都在1-6中间,也就是说这一段都要更新,那么我们将1-5的sum值更新了,同时用col[rt]+=3记录下来1-5中的数字现在每个都要加的数字,但是1-5下边还有1-3,4-5,3-3,4-4,5-5,这些我们就可以不用更新,因为这些我们暂时还用不到,假如现在又要将1-5区间的值都加5,那么col[rt]+=5,此时就是8了,但是还是不用更新他的子节点,假如我们现在要用到1-3区间了,我们就可以一次性给1-3区间加上8,而不用先加3,再加5,这样懒惰标记就使得每次的递归都少了好多。

以上图为例,我先更新[5-7]区间的数为3,此时程序跑完之后会将sum[3] = 3(sum数组下标即为叶子结点),而节点3之后的叶子节点暂不更新,之后我又更新了[4-7]区间的数为2,程序跑一遍,将sum[3] = 2(叶子节点不再往下更新),sum[11] = 2,最后我更新了[5-6]区间的数为1,因为区间[5-6]包含在区间[5-7]里面,所以程序往[5-7]这个大节点跑下去,节点3之前打过懒惰标记,此时程序将更新之前在[5-7]区间未更新的叶子节点,按照完全二叉树建立的特点很容易明白sum[rt<<1] = (m - (m >> 1)) * col[rt];sum[rt<<1|1] = (m >> 1) * col[rt];这两句代码中col[rt]前面的系数为什么如此写。如果程序最后更新的是[4-6]区间,那么程序出了跑[5-7]这个大区间之外,额外跑一个节点11.

#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l ,m ,rt << 1
#define rson m + 1 ,r , rt << 1 | 1
const int maxn = 100005;
int sum[maxn<<2],col[maxn<<2];

void PushUp(int rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

void PushDown(int rt,int m)
{
    if (col[rt])
    {
        col[rt<<1] = col[rt<<1|1] = col[rt];
        sum[rt<<1] = (m - (m >> 1)) * col[rt];
        sum[rt<<1|1] = (m >> 1) * col[rt];
        col[rt] = 0;
    }
}

void build(int l,int r,int rt)
{
    col[rt] = 0;
    sum[rt] = 1;
    if (l == r) return;
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
}

void upd(int L,int R,int c,int l,int r,int rt)
{
    if (L <= l && r <= R)
    {
        col[rt] = c;
        sum[rt] = (r - l + 1) * c;
        return;
    }
    PushDown(rt,r - l + 1);
    int m = (l + r) >> 1;
    if (L <= m) upd(L,R,c,lson);
    if (R > m)  upd(L,R,c,rson);
    PushUp(rt);
}

int main()
{
    int T;
    scanf("%d",&T);
    for (int i =1;i <= T;i++)
    {
        int n,m,x,y,z;
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while (m--)
        {
            scanf("%d%d%d",&x,&y,&z);
            upd(x,y,z,1,n,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",i,sum[1]);
    }
    return 0;
}

HDU 1698 Just a Hook(线段树/区间更新)的更多相关文章

  1. (简单) HDU 1698 Just a Hook , 线段树+区间更新。

    Description: In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of ...

  2. HDU 1698 Just a Hook(线段树区间更新查询)

    描述 In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes ...

  3. HDU 1698 Just a Hook 线段树区间更新、

    来谈谈自己对延迟标记(lazy标记)的理解吧. lazy标记的主要作用是尽可能的降低时间复杂度. 这样说吧. 如果你不用lazy标记,那么你对于一个区间更新的话是要对其所有的子区间都更新一次,但如果用 ...

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

    Just a Hook [题目链接]Just a Hook [题目类型]线段树 区间替换 &题解: 线段树 区间替换 和区间求和 模板题 只不过不需要查询 题里只问了全部区间的和,所以seg[ ...

  5. [HDU] 1698 Just a Hook [线段树区间替换]

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

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

    题目地址:pid=1698">HDU 1698 区间替换裸题.相同利用lazy延迟标记数组,这里仅仅是当lazy下放的时候把以下的lazy也所有改成lazy就好了. 代码例如以下: # ...

  7. hdu - 1689 Just a Hook (线段树区间更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=1698 n个数初始每个数的价值为1,接下来有m个更新,每次x,y,z 把x,y区间的数的价值更新为z(1<= ...

  8. HDU.1689 Just a Hook (线段树 区间替换 区间总和)

    HDU.1689 Just a Hook (线段树 区间替换 区间总和) 题意分析 一开始叶子节点均为1,操作为将[L,R]区间全部替换成C,求总区间[1,N]和 线段树维护区间和 . 建树的时候初始 ...

  9. HDU.1556 Color the ball (线段树 区间更新 单点查询)

    HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...

  10. Just a Hook 线段树 区间更新

    Just a Hook In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of t ...

随机推荐

  1. CAP原理的证明

    CAP概述 C: Consistency 一致性 A: Availability 可用性 P:Partition Tolerance分区容错性 CAP理论的核心是:一个分布式系统不可能同时很好的满足一 ...

  2. Web性能优化-合并js与css,减少请求

    Web性能优化已经是老生常谈的话题了, 不过笔者也一直没放在心上,主要的原因还是项目的用户量以及页面中的js,css文件就那几个,感觉没什么优化的.人总要进步的嘛,最近在被angularjs吸引着,也 ...

  3. C#读取网络流,读取网络上的js文件

    写博客的目的就是让其他人少走弯路. C#读取网络上的流和js文件出现的问题 一开始看了今天博客园上的推荐文章,用C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子),然 ...

  4. JAVA_集合框架虐我千百遍,虐也是一种进步

    1.Collection和Collections区别: Collection是java的一个集合接口,集合类的顶级接口 Collections是一个包装类(工具类),不能被实例化(由于其构造函数设为私 ...

  5. PC互联网和移动互联网的本质差别

    网一代,我们先称为PC互联网,这大约可以从2010年作为分界,然后就是基于手机,及可穿戴的移动互联网. 在PC时代,软件都很庞大复杂,甚至客端端和网页混合,比如常见的桌面软件,Office及Photo ...

  6. sql 重复数据只保留一条

    用SQL语句,删除掉重复项只保留一条在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 select * ...

  7. js的Array的map和sort实现方法

    Array.prototype.mapA = function(fun /*, thisp*/) { var len = this.length; if (typeof fun != "fu ...

  8. SNMP 原理与实战详解

    原文地址:http://freeloda.blog.51cto.com/2033581/1306743 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...

  9. JavaScript返回上一级,并重新加载页面

    window.location.href = document.referrer;

  10. Android之Activity启动模式

    正常模式 每个应用都有一个任务栈,任务栈中保存着已创建的Activity,先创建的Activity先入栈,栈顶是当前正在显示的activity(running),这是正常模式下的Activity的管理 ...