继续看NotOnlySuccess有关线段树的讲解...先头捣腾了一下线段树单位点更新的问题...刚才看了一段一段更新的问题..A了一道模板题(http://acm.hdu.edu.cn/showproblem.php?pid=1698)..
总的来说一段一段的更新和只更新单位点的差别不是很大...不同的地方主要是在更新树的时候...也就是Updata时..先贴一下Updata的程序段
void updata(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]; }
可以看出成段更新时的Updata和单点更新时的GetSum很相似...回顾一下单点更新的GetSum就是询问一段..然后给出一段的值...这里是给出一段...更新一段的值...自然有类似之处了..这个程序的重要的地方就是用了一个延迟标记col..即每次更新不是一直更新到叶子结点...下一次更新时如果要继续下去才会往下走...这样省去了很多无谓的操作..比如有一个线段1-5..我更新了2-3...问1-5这一段的情况...如果没用延迟标记...或许要往下递归很多次才能返回值...而用了延 ...迟标记...一层就能返回结果...这就很高效了...Updata里的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; } }