基础线段树,插线问线
这道题是成段更新,使用延迟标记,对于当前的left<=l&&right>=r直接返回,(等到找到叶子结点时候,在开始向上回溯对父亲结点进行结点求和,算值;(1))等到下次更新搜索到时候才向下更新.
即:T[root].val=T[L(root)].val+T[R(root)].val;
#include<stdio.h>
#include<string.h>
#define L(t)(t<<1)
#define R(t)(t<<1|1)
#define MID(a,b)((a+b)>>1)
const int MAX=100002;
struct Node
{
int l,r,val,kind;
}T[MAX<<2];
void Build(int l,int r,int root)
{
T[root].l=l;T[root].r=r;
T[root].val=r-l+1;
T[root].kind=1;
if(l==r)return;
int m=MID(l,r);
Build(l,m,L(root));
Build(m+1,r,R(root));
}
void Modify(int l,int r,int root,int kind)
{
if(T[root].kind==kind)return; //剪枝,如果相同就无需再更新
if(l<=T[root].l&&r>=T[root].r) //(1)
{
T[root].val=(T[root].r-T[root].l+1)*kind;
T[root].kind=kind;
return;
}
if(T[root].kind!=0) //(2) T[root].kind!=0判断该节点的儿子是否更新过
{
T[L(root)].kind=T[root].kind;
T[L(root)].val=(T[L(root)].r-T[L(root)].l+1)*T[L(root)].kind;
T[R(root)].kind=T[root].kind;
T[R(root)].val=(T[R(root)].r-T[R(root)].l+1)*T[R(root)].kind;
T[root].kind=0;
}
int m=MID(T[root].l,T[root].r);
if(r<=m)
Modify(l,r,L(root),kind);
else if(l>m)
Modify(l,r,R(root),kind);
else{
Modify(l,m,L(root),kind);
Modify(m+1,r,R(root),kind);
}
T[root].val=T[L(root)].val+T[R(root)].val; //(1)
}
int main()
{
int N,i,n,t,a,b,kind;
scanf("%d",&N);
for(i=1;i<=N;i++)
{
scanf("%d",&n);
Build(1,n,1);
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&a,&b,&kind);
Modify(a,b,1,kind);
}
printf("Case %d: The total value of the hook is %d.\n",i,T[1].val);
}
return 0;
}