用线段树对一个区间的所有树进行更新所进行的操作与利用线段树对一个区间的
单间进行更新的操作有所不同。单点更新时先找到要更新的点,然后再
向上回溯,将祖先更新。而对整个区间的数据进行更新时如此这般,
效率会很低。所以当我们区间更新时,当从根节点向下不断缩小
区间时,一旦锁定了区间就直接计算出该区间更新后的值,然后
给该节点打上lazy标志,接着不会继续向下更新,而是向上
回溯更新祖先节点,而lazy所标识的节点孩子节点的数据并没有
更新,只有当下次更新或查询经过这个节点时,才会向下更新。
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=111111;
int lazy[100010<<2],seg[100010<<2];
void upGo(int rt)
{
seg[rt]=seg[rt<<1]+seg[rt<<1|1];
}
void pushDown(int rt,int len)
{
if(lazy[rt])
{
lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];///将延迟标志传给rt的左右子树
seg[rt<<1]=lazy[rt]*(len-(len>>1));///直接计算更新后rt左右子树的值,而不是通过下向上累加来更新值
seg[rt<<1|1]=lazy[rt]*(len>>1);
lazy[rt]=0;
}
}
void build(int rt,int l,int r)
{
lazy[rt]=0;
seg[rt]=1;
if(l==r)return;
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
upGo(rt);
}
void upDate(int rt,int l,int r,int a,int b,int value)
{
if(a<=l&&r<=b)
{
lazy[rt]=value;
seg[rt]=value*(r-l+1);
return;
}
pushDown(rt,r-l+1);
int mid=(l+r)>>1;
if(a<=mid)upDate(rt<<1,l,mid,a,b,value);
if(b>mid) upDate(rt<<1|1,mid+1,r,a,b,value);
upGo(rt);
}
int main()
{
int t,n,m;cin>>t;
for(int cas=1;cas<=t;cas++)
{
cin>>n>>m;
build(1,1,n);
while(m--)
{
int a,b,z;cin>>a>>b>>z;
upDate(1,1,n,a,b,z);
}
printf("Case %d: The total value of the hook is %d.\n",cas,seg[1]);
}
}