线段树(三)——杨子曰算法

线段树(三)——杨子曰算法

传送门:线段树(一)
传送门:线段树(二)


给一段长度为n(n<=200000)的序列,接着是m(m<=20000)个操作对于每个操作显示一个k,如果k=1那么输入一个x,输出第x个元素,如果k=2,那么输入x,y,z,将区间[x,y]的每一个元素都加上z


接着上次的问题,我们开始曰今天的内容,这道题与之前拿那道最大的区别就是它更新的内容是——一个区间,哦,瞬间有大佬发话了,这岂不是很简单,就像上次的区间query一样,分三种情况讨论,全在左区间,全在右区间,以及一半在左,一半在右,然后递归下去就完了,但是有一个很大的区别,就是找到的区间和要更新的区间完全吻合时,不能停止,还要在往下走(因为我对整个区间都要更新,如果不更新,你要输出某个叶子结点时,这个叶子结点还没有更新,于是WA)
呵呵,你以为你想出的是正解,NO!,假设我想在要更新整个区间[1,n],你就得遍历整棵树,复杂度是O(n)的,然后有一个恶心数据m个询问全是更新整个区间,复杂度O(mn),恭喜TLE,正解优化走起


今天,我们来曰一个线段树上的区间更新的优化——lazy标记(懒标记?一个奇怪的名字,到下面就能明白,这个名字是怎么来的),意思就是当找到的区间和要更新的区间完全吻合时——停止,然后在这个结点做一个标记,这个标记就是LAZY标记,呀呀呀,不刚刚说过会WA吗,不要紧张嘛,我们只需要在即将要递归它的儿子的时候,把这个lazy标记下放(←专业人士称之为pushdown),注意,只要需要递归某个结点的儿子,不管你要搞什么事情,update也好,query也好,还是搞笑也好,只要往下走了,就要先把lazy给pushdown掉,懂否?,pushdown走起:

void pushdown(){
    lazy[nod*2]+=lazy[nod];
    lazy[nod*2+1]+=lazy[nod];
    lazy[nod]=0;//灰常重要,千万要把下方的lazy清空
}

对于这道题而言,我们只要记录,某个区间的每个数字的统一变化量就行了(←就是记录lazy)因为它的询问只需要输出某个数的值,最后输出的时候,递归到叶子节点,把这个元素的变化量加上原来的数不久欧了吗?
所以,我觉得不!用!build!(★,°:.☆( ̄▽ ̄)/$:.°★ 。)只要把原来线段树全赋成0就行了(因为开始时lazy都是0),这时的query就跟线段树(二)里那题的update差不多了,都类似一个二分,不多解释,Don‘t 忘记 to pushdown 代码走起:

int query(int l,int r,int k,int nod){
    if (l==r){
        return lazy[nod]+a[k];
    }//到叶子结点
    pushdown(nod);//注意注意注意
    int mid=(l+r)/2;
    if (k<=mid) return query(l,mid,k,nod*2);
    else return query(mid+1,r,k,nod*2+1);
}

来,看update,区间吻合时更新下lazy,结束,有没有觉得更上次的query一样,还是熟悉的三种情况(如果你是鱼的记忆,请往上翻),直接代码走起:

void update(int l,int r,int ll,int rr,int v,int nod){
    if (l==ll && r==rr){
        lazy[nod]+=v;
        return;
    }//区间完全吻合
    pushdown(nod);//不要忘啊不要忘啊不要忘啊
    int mid=(l+r)/2;
    if (rr<=mid) update(l,mid,ll,rr,v,nod*2);//全在左区间
    else if (ll>mid) update(mid+1,r,ll,rr,v,nod*2+1);//全在右区间
    else {
        update(l,mid,ll,mid,v,nod*2)//一半在左
        update(mid+1,r,mid+1,rr,v,nod*2+1)//一半在右
    }
}

OK,完事
好了,到目前为止,你已经能解决大部分的区间线段树问题了
BUT,杨子曰过:“对未知的探索是永无止境滴”
So,线段树(四),预告:


给一个长度为n(n<=200000)的序列,再给出m个操作,对于每个操作,先给出一个k,如果k=1,则输入x,y,输出区间[x,y]的和,如果k=2,则输入x,y,z,把区间[x,y]的每个元素加上z
OK,88
传送门:线段树(四)
于TJQ高层小区902
未经作者允许,严禁转载:https://blog.csdn.net/HenryYang2018/article/details/79844739

猜你喜欢

转载自blog.csdn.net/henryyang2018/article/details/79844739