HDU 1698 【线段树区间更新】

之前一直觉得自己线段树敲得很熟练,然后。。。某天。。。是的,就是我的数据结构周开始的时候我发现。。。我特么才会单点更新是怎么回事!只会区间查找是肿么回事!!摔!

恩。。。就是表达一下弱渣的心情。。。。

区间更新,用到延迟操作。

延迟操作应该是这么回事。线段树的优越性就是体现在,第一是二分查找,第二是区间操作。当我们需要多次对区间进行操作的时候,如果每次都更新每个区间内的每个节点,那么线段树的优势就不复存在啦!所以,对区间进行延迟操作,就是操作该区间的时候,标记该区间,表示操作过,但是对其子区间不进行更新。然后如果下一次我还要操作这个区间,或者是它的子区间,那么我就在对它的子区间进行上一次未完成的更新。并且下次操作是上次操作的子区间,所以一定会“经过”上次操作的区间,如果发现被标记了,表示接下来的区间未更新,就顺便在查找下次操作的区间的时候把上次操作的更新完成,并且将这种状态(操作or未操作)传递给子区间的子区间。

强烈建议画一个[1,10]的线段树,自己划两下比想一个小时管用多了。

#include <stdio.h>
#define maxn 100010
int tree[maxn<<2],col[maxn<<2];
void create(int l,int r,int rt)
{
    tree[rt]=col[rt]=0;
    if(l==r){tree[rt]=1;return;}
    int mid=(l+r)>>1;
    create(l,mid,rt<<1);create(mid+1,r,rt<<1|1);
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void pushdown(int rt,int d)
{
    if(col[rt])
    {
        col[rt<<1]=col[rt<<1|1]=col[rt];
        tree[rt<<1]=(d-(d>>1))*col[rt];
        tree[rt<<1|1]=(d>>1)*col[rt];
        col[rt]=0;
    }
}
void update(int ll,int rr,int l,int r,int rt,int c)
{
    if(ll==l&&rr==r)
    {
        col[rt]=c;tree[rt]=c*(r-l+1);
        return;
    }
    pushdown(rt,r-l+1);
    int mid=(l+r)>>1;
    if(rr<=mid) update(ll,rr,l,mid,rt<<1,c);
    else if(ll>mid) update(ll,rr,mid+1,r,rt<<1|1,c);
    else {update(ll,mid,l,mid,rt<<1,c);update(mid+1,rr,mid+1,r,rt<<1|1,c);}
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
int main()
{
    int T,cas=0;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        create(1,n,1);
        while(m--)
        {
            int l,r,c;
            scanf("%d%d%d",&l,&r,&c);
            update(l,r,1,n,1,c);
        }
        printf("Case %d: The total value of the hook is %d.\n",++cas,tree[1]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值