题目链接:点击打开链接
//区域更新 区域查询
//需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候
//PushDown()需要认真想明白;
//大体意思是:
//每次查询到(L,R)大于(l,r)的区间,先把此段更新(或是替换原来的col),然后回溯,更新(PushUp)父节点们
//不先去管子节点们,反正已经此段标记过了
//当查询到的段不为 (L,R)大于(l,r)的区间,就要考虑当前段->是否之前更新的还未传给子节点(此段col不为零说明未传给子节点)
//需要PushDown()一下(记得取消此段的col标记),让子节点成为之前应变成但未变成的样子,再去处理子节点
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define MAXN 100005
int setTree[MAXN<<2];
int col[MAXN<<2];
void PushUp(int root){
setTree[root]=setTree[root<<1]+setTree[root<<1|1];
}
void PushDown(int root,int wideth){
if(col[root]){
col[root<<1]=col[root<<1|1]=col[root];
setTree[root<<1]=col[root]*(wideth-(wideth>>1));
setTree[root<<1|1]=col[root]*(wideth>>1);
col[root]=0;
}
}
void Build(int l,int r,int root){
col[root]=0;
if(l==r){
setTree[root]=1;
return;
}
int m=(l+r)>>1;
Build(l,m,root<<1);
Build(m+1,r,root<<1|1);
PushUp(root);
}
void Update(int L,int R,int key,int l,int r,int root){//区域更新最关键也是最难理解的地方
if(L<=l&&R>=r){
setTree[root]=((r-l)+1)*key;
col[root]=key;
return;
}
PushDown(root,r-l+1);
int m=(l+r)>>1;
if(L<=m)
Update(L,R,key,l,m,root<<1);
if(R>m)
Update(L,R,key,m+1,r,root<<1|1);
PushUp(root);
}
int main(){
int t,m,n;
int x,y,z;
cin>>t;
for(int i=1;i<=t;i++){
cin>>n>>m;
Build(1,n,1);
for(int j=1;j<=m;j++){
scanf("%d%d%d",&x,&y,&z);
Update(x,y,z,1,n,1);
}
printf("Case %d: The total value of the hook is %d.\n",i,setTree[1]);
}
return 0;
}