lazy思想:
每次更新只要更新到题目要求的区间即可,然后更新此区间节点data值,
记录tree[num].lazy(等于题目要求更新的值wei),
下次要用到的时候就传递给左右子树,更新左右子树的data值。
每次更新只要更新到题目要求的区间即可,然后更新此区间节点data值,
记录tree[num].lazy(等于题目要求更新的值wei),
下次要用到的时候就传递给左右子树,更新左右子树的data值。
并且将当前lazy归0.
运用lazy思想,就不用每次都更新(或查找)到叶子节点,在某些数据比较大的时候会节省很多时间。
以HDU1698为例
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct node
{
int l,r,m,data,lazy;
}tree[3*100005];
void creat(int num,int le,int ri)
{
tree[num].l=le;
tree[num].r=ri;
tree[num].m=(le+ri)/2;
if(le==ri)
{
tree[num].data=1;
tree[num].lazy=0;
return ;
}
creat(2*num,le,tree[num].m);
creat(2*num+1,tree[num].m+1,ri);
}
void insert(int num,int le,int ri,int k)
{
if(tree[num].l==le&&tree[num].r==ri)
{
tree[num].data=(ri-le+1)*k; //找到后更新data
tree[num].lazy=k; //lazy标记
return ;
}
if(tree[num].lazy!=0) //重点!!!是否之前有遍历过
{
tree[2*num].lazy=tree[num].lazy; //将lazy传递给左子树
tree[2*num+1].lazy=tree[num].lazy; //传递给右子树
tree[2*num].data=(tree[2*num].r-tree[2*num].l+1)*tree[num].lazy; //更新左右子树的data值
tree[2*num+1].data=(tree[2*num+1].r-tree[2*num+1].l+1)*tree[num].lazy;
tree[num].lazy=0; //将当前区间节点归零,会有返回值更新data值。
}
if(ri<=tree[num].m)
insert(2*num,le,ri,k);
else if(le>tree[num].m)
insert(2*num+1,le,ri,k);
else
{
insert(2*num,le,tree[num].m,k);
insert(2*num+1,tree[num].m+1,ri,k);
}
tree[num].data=tree[2*num].data+tree[2*num+1].data;
}
int main()
{
int t,n,le,ri,wei,i,q,j;
scanf("%d",&t);
for(i=1;i<=t;i++)
{
memset(tree,0,sizeof(tree)); //每次最好都初始化线段树。此题没初始化WA!!!
scanf("%d%d",&n,&q);
creat(1,1,n);
for(j=1;j<=q;j++)
{
scanf("%d%d%d",&le,&ri,&wei);
insert(1,le,ri,wei);
}
printf("Case %d: The total value of the hook is %d.\n",i,tree[1].data);
}
return 0;
}