VJ Just a Hook(线段树区间修改+查询)

原题
这题就是线段树区间修改板子题,没什么坑,主要是熟悉懒标记的使用

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
struct tree
{
    ll l,r;
    ll sum,lazy;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sum(x) tree[x].sum
#define lazy(x) tree[x].lazy
} tree[500005];
ll n,m;
void build(ll p,ll l,ll r)
{
    l(p)=l,r(p)=r;
    if(l==r)
    {
        sum(p)=1;
        return ;
    }
    ll mid=l+r>>1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    sum(p)=sum(2*p)+sum(2*p+1);
}
void spread(ll p)
{
    if(lazy(p))
    {
        lazy(p*2)=lazy(p*2+1)=lazy(p);//这里因为是把一段区间的所有数都改成相同的数,直接左右节点懒标相等就好了
        sum(p*2)=lazy(p)*(r(p*2)-l(p*2)+1);//就是这里的 +1 ,半天找不出来
        sum(p*2+1)=lazy(p)*(r(p*2+1)-l(p*2+1)+1);
        lazy(p)=0;//记得清除标记
    }
}
void change(ll p,ll l,ll r,ll v)
{
    if(l<=l(p)&&r(p)<=r)
    {
        sum(p)=v*(r(p)-l(p)+1);
        lazy(p)=v;
        return ;
    }
    ll mid=l(p)+r(p)>>1;
    spread(p);//下传懒标记
    if(l<=mid)
        change(p*2,l,r,v);
    if(r>mid)
        change(p*2+1,l,r,v);
    sum(p)=sum(p*2)+sum(p*2+1);
}
int main()
{
    ll T,cot=1;
    cin>>T;
    while(T--)
    {
        memset(tree,0,sizeof(tree));
        scanf("%lld",&n);
        build(1,1,n);
        scanf("%lld",&m);
        while(m--)
        {
            ll l,r,v;
            scanf("%lld%lld%lld",&l,&r,&v);
            change(1,l,r,v);
        }
        printf("Case %lld: The total value of the hook is %lld.\n",cot++,sum(1));
    }
    return 0;
}

这题我看了网上很多题解,大多是不使用结构体而是开了数组,并且 change 函数的形参比较多。
但我坚持使用了《算法竞赛进阶指南》的写法,所以在做这题时debug了好久,一直找不到错误,但最后 AC 时的快感真是太爽了!
主要也是想借此加深自己对线段树的理解,同时形成一个自己接受的代码风格

posted @ 2020-03-11 21:50  Pecoz  阅读(119)  评论(0编辑  收藏  举报