HDU1698 just a Hook

2017-08-30 16:44:33

writer:pprp

上午刚刚复习了一下不带有lazy标记的线段树,

下午开始学带有lazy标记的线段树

这个是我看大佬代码敲的,但是出了很多问题,

这提醒我:

1、要注意边界条件,一个边界条件的取等或者不取等,小于或者大于出错的话就直接运行不了了

2、注意输入输出,经过多次测试,果然还是用scanf比较保险,试了试用fast_io的cin结果还是TLE

  所以以后不要用cin了,cin害人啊,两个混用就更加麻烦了

这个题就是区间修改,区间查询的一道题,但是大佬没有用指针构造一个结构体

仅仅抽象了一个sum和一个add(lazy标记)

感觉简单了不少

代码如下:

/*
@theme:segmentation/interval tree
@writer:pprp
@begin:15:26
@end:16:13
@declare: 使用lazy标记的线段树,HDU 1698
@date:2017/8/30
*/

#include <iostream>
#include <cstdio>
#define Mid ((l+r)>>1)
#define lson rt<<1,l,Mid
#define rson rt<<1|1,Mid+1,r
const int maxn = 100010;
int sum[maxn<<2],add[maxn<<2];

using namespace std;

void build(int rt,int l, int r)
{
    add[rt] = 0;
    //这里是每个节点都是1的情况
    if(l == r)
        sum[rt] = 1;
    else
    {
        build(rson);
        build(lson);
        sum[rt] = sum[rt<<1]+sum[rt<<1|1];
    }
}


void pushDown(int rt, int len)
{
    //将父节点的add值传递下来
    add[rt<<1] = add[rt<<1|1] = add[rt];
    //将左右的值进行区间更新
    sum[rt<<1] =  (len - (len>>1))*add[rt];
    sum[rt<<1|1] = (len>>1)*add[rt];
    //将父节点的add值清空
    add[rt] =0;
}




//L,R代表的要更新区间的左右端点,z是区间增加的值
void update(int rt, int l,int r, int L, int R, int z)
{
    //如果在L,R的内部
    if(L <= l && r <= R)   //error before
    {
        add[rt] = z;
        sum[rt] = (r - l + 1) * z;
    }
    else  //没有找到该节点
    {
        if(add[rt])//当前节点不为空,要传下去
            pushDown(rt,r-l+1);
        if(L <= Mid)
            update(lson,L,R,z);
        if(R > Mid) //error before
            update(rson,L,R,z);
        sum[rt] = sum[rt<<1]+sum[rt<<1|1];
    }
}

int main()  
{  
//    RE;  
    int t,n,q,x,y,z;  
    int cnt=1;  
    scanf("%d",&t);  
    while(t--){  
        scanf("%d%d",&n,&q);  
        build(1,1,n);  
        while(q--){  
            scanf("%d%d%d",&x,&y,&z);  
            update(1,1,n,x,y,z);  
        }  
        printf("Case %d: The total value of the hook is %d.
", cnt++,sum[1]);  
    }  
    return 0;  
}  
原文地址:https://www.cnblogs.com/pprp/p/7453945.html