线段树(区间更新) hdu-1698-Just a Hook

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1698

 

题目意思:

有n个棒子,每个棒子都有一个值,q个更新,每次更新时有三个参数x,y,z表示,把x-y区间内的棒子的值改成z,为最后所有棒子的值的总和是多少。

 

解题思路:

建一个n大小的线段树,用sum[rt]表示该节点区间的值总和,value[rt]表示该区间当前所处的状态,如果为非零则表示该区间内所有棒子为该值,并且没有传下去,如果为零,说明该区间内的状态改变都已传下去了。每次更新完毕后将该区间的sum值求出(向上更新),最后输出sum[1]即可。

关键:更新延迟,不是每次更新都更新到叶子节点,记录状态等下次更新时再往下更新,但每次都把顶层的sum值给求出来。

 

详见代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF (1<<30)
#define PI acos(-1.0)
using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,(rt<<1)|1
#define maxn 110000
int sum[maxn*4],value[maxn*4]; //作为标记如果为非零则表示没有向下传

/*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/

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

void build(int l,int r,int rt)
{
    value[rt]=0; //不需往下传
    sum[rt]=1;//叶子节点,开始均为铜1

    if(l==r)
        return ;
    int m=(l+r)>>1;

    build(lson);
    build(rson);
    pushup(rt);
    return ;
}

void pushdown(int rt,int num) //向下传,num为该区间点的总的个数
{
    if(value[rt])
    {
        value[rt<<1]=value[rt<<1|1]=value[rt];
        sum[rt<<1]=(num-(num>>1))*value[rt];  //注意前一区间可能后一区间多一,所以前一区间可能比后面多一个
        sum[rt<<1|1]=(num>>1)*value[rt];
        value[rt]=0;//表示该节点以向下更新,下次不必下传了
    }
    return ;
}

void update(int L,int R,int v,int l,int r,int rt)
{
    if(L<=l&&R>=r)  //如果要查找的区间包括当前空间,就不往下更新了,保存
    {
        value[rt]=v;
        sum[rt]=v*(r-l+1);
        return ;
    }
    //如果不能包括该区间,说明要分,先将上次的传下去
    pushdown(rt,r-l+1);

    int m=(l+r)>>1;

    if(L<=m)
        update(L,R,v,lson);//必须更新左边
    if(R>m)
        update(L,R,v,rson);//必须更新右边
    pushup(rt); //向上传
    return ;
}


int main()
{
    int ca,n,q;

    scanf("%d",&ca);
    for(int k=1;k<=ca;k++)
    {
        scanf("%d%d",&n,&q);
        build(1,n,1);
        while(q--)
        {
            int a,b,c;

            scanf("%d%d%d",&a,&b,&c);
            update(a,b,c,1,n,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",k,sum[1]);

    }
    return 0;
}












 

 

你可能感兴趣的:(线段树(区间更新) hdu-1698-Just a Hook)