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 时的快感真是太爽了!
主要也是想借此加深自己对线段树的理解,同时形成一个自己接受的代码风格
戒骄戒躁,百炼成钢!