P3373 【模板】线段树 2(题解)
线段树解法 好丢脸,这个题做了一下午,调试了三个多小时...... 先讲讲解题思路 既然这里是线段树,就要用到lazy—tag。又有加法又有乘法的话,就要用到两个lazy-tag,分别用数组jia[]和chng[]表示。线段树用数组t[]存。 我们让lazy-tag还原数值时,先乘chng[],再加jia[](人为规定,这样好算) 怎么维护lazy-tag? 加法 void add( k, l, r, x, y, delta) { 函数的作用是在编号为k,区间是[l,r]的线段树里,给区间[x,y]里的每一个数加上delta。 如果当前区间[l,r]和目标区间[x,y]完全重合,就要在当前这颗编号为k的树上标记。 首先jia[k]要加上delta,表示当前区间[l,r](即[x,y])内的每一个数都加了delta; 然后要修改t[k]的值,也就是加上区间内增加的总数,即t[k]+=delta*(r-l+1); return。 如果当前区间不与目标区间完全重合,就要对子树操作。 首先,标记下传,用pushdown()函数将树k的标记全数下传给两个儿子k*2和k*2+1; 然后,先取mid=(l+r)>>1,判断一下目标区间是在当前区间的左子树区间、还是右子树区间、还是左右都有; (如果y<=mid,那么目标区间一定只在左子树里;如果x>=mid+1,那么目标区间一定只在右子树里