题目链接: 传送门

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. async 更优雅异步体验

    上一篇<让 Generator 自启动>介绍了通过起动器让 Generator 跑起来,而本篇采用 async 实现更优雅的异步编程. 从例子开始 借用上一篇例子中的例子说起. funct ...

  2. 【REST WCF】30分钟理论到实践

    先来点理论知识,来自 http://www.cnblogs.com/simonchen/articles/2220838.html 一.什么是Rest REST软件架构是由Roy Thomas Fie ...

  3. Bootstrap系列 -- 40. 导航条二级菜单

    在导航条中添加二级菜单也非常简单 <div class="navbar navbar-default" role="navigation"> < ...

  4. Linux下网络流量实时监控工具

    Linux下网络流量实时监控工具大全 在工作中发现,经常因为业务的原因,需要即时了解某台服务器网卡的流量,虽然公司也部署了cacti软件,但cacti是五分钟统计的,没有即时性,并且有时候打开监控页面 ...

  5. NHibernate无法将类型“System.Collections.Generic.IList<T>”隐式转换为“System.Collections.Generic.IList<IT>

    API有一个需要实现的抽象方法: public IList<IPermission> GetPermissions(); 需要注意的是IList<IPermission>这个泛 ...

  6. 流量工程 traffic engineering (TE)

    什么是流量工程 流量工程是指根据各种数据业务流量的特性选取传输路径的处理过程.流量工程用于平衡网络中的不同交换机.路由器以及链路之间的负载. [编辑] 流量工程的内容 流量工程在复杂的网络环境中,控制 ...

  7. SqlServer中——查找杀死阻塞进程

    查找阻塞进程: SELECT blocking_session_id '阻塞进程的ID', wait_duration_ms '等待时间(毫秒)', session_id '(会话ID)' FROM ...

  8. 东大OJ 2SAT 异或

    看了十年才懂懂了十年才会会了十年才会写写了十年才写完写完了十年才能改对 #include<stdio.h> #include<string.h> struct res{ int ...

  9. PagerAdapter 用法

    PagerAdapter简介 PagerAdapter是android.support.v4包中的类,它的子类有FragmentPagerAdapter, FragmentStatePagerAdap ...

  10. Android 轻量级输入校验库:Fire Eye

    Fire Eye是一款轻量级简单易用的Android校验库. FireEye 2.0 在 1.0 的基础上,全部重写了代码,并优化了架构,性能上和逻辑上都大大提升.只需要几行代码,即可验证用户输入,并 ...