线段树初步应用(一段一段的更新) HDOJ - 1698
原创
©著作权归作者所有:来自51CTO博客作者zzyzzy12的原创作品,请联系作者获取转载授权,否则将追究法律责任
继续看NotOnlySuccess有关线段树的讲解...先头捣腾了一下线段树单位点更新的问题...刚才看了一段一段更新的问题..A了一道模板题(http://acm.hdu.edu.cn/showproblem.php?pid=1698)..
总的来说一段一段的更新和只更新单位点的差别不是很大...不同的地方主要是在更新树的时候...也就是Update时..先贴一下Update的程序段
void update(int L,int R,int data,int l,int r,int sp)
{
if (L<=l && R>=r)
{
col[sp]=data;
sum[sp]=data*(r-l+1);
return;
}
PushDown(sp,r-l+1); /// 重点..
int Mid=(l+r)/2;
if (Mid>=L) updata(L,R,data,l,Mid,sp*2);
if (Mid< R) updata(L,R,data,Mid+1,r,sp*2+1);
sum[sp]=sum[sp*2]+sum[sp*2+1];
}
可以看出成段更新时的Update和单点更新时的GetSum很相似...回顾一下单点更新的GetSum就是询问一段..然后给出一段的值...这里是给出一段...更新一段的值...自然有类似之处了..这个程序的重要的地方就是用了一个延迟标记col..即每次更新不是一直更新到叶子结点...下一次更新时如果要继续下去才会往下走...这样省去了很多无谓的操作..比如有一个线段1-5..我更新了2-3...问1-5这一段的情况...如果没用延迟标记...或许要往下递归很多次才能返回值...而用了延 ...迟标记...一层就能返回结果...这就很高效了...Update里的PushDown是更新单位点的线段树所没有..其作用就是调整延迟标记和sum:
void PushDown(int sp,int data)
{
if (col[sp])
{
col[sp*2]=col[sp]; col[sp*2+1]=col[sp];
sum[sp*2]=(data-data/2)*col[sp];
sum[sp*2+1]=(data/2)*col[sp];
col[sp]=0;
}
}