zoukankan      html  css  js  c++  java
  • 线段树延迟更新


    title: 线段树延迟更新
    date: 2018-10-10 18:50:49
    tags:

    • acm
    • 算法
      categories:
    • ACM-线段树

    概述

    暑假集训的时候好多东西只学了个皮毛,,,对付模板题还能试试,,,但是一看一些稍难的一些题时,,,肯定单纯的套模板是不行得了,,,那样多没意思啊,,,

    延迟更新之前就看到过,,,当初的映像就是在普通的线段树里加一个lazy,,,然后可以延迟更新区间,,,这在对区间整段的更新很有用,,,因为不用对更新区间的每一个点更新,,这样就能省下很多时间,,,

    但是,,那时没时间也看不懂,,,跟别提怎么操作了,,,,

    国庆的时候专门看看了看这块知识,,,大概了解了lazy的作用以及该怎么使用他,,

    当时是看这篇博客的

    分析

    单纯的线段树主要是 单点修改,区间查询 ,,,

    若是不更改进行区间的修改时,,,只能对区间里的每一个数进行单点修改,,,当数据量很大时,,这样的操作很费时间,,,

    所以可以对每一个节点都加一个lazy标记,,,当这一段要更新时,,父节点的lazy更新,,然后区间所维护的sum加上相应的几倍的lazy,,,,这样该节点对上时更新后的值,,向上正确,,,而对于它的两个子节点,,,只将lazy更新表明这里需要更新,,,但是并没有继续向下更新,,,这一段的操作由pushdown()函数完成,,,

    实现和练习

    看个具体的例子:题目链接,,,

    题目意思很简单,,,就是初始长度为n的一个数列值全为1,,

    然后对某些区间进行赋为1 , 2 , 3的操作,,,最后问你在这些操作之后这一段的和是多少,,,

    具体的实现如下:

    //#include <bits/stdc++.h>
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #define ll long long
    
    const int maxn = 1e5 + 5;
    //因为初始值全为一所以没有a[maxn]
    struct tree
    {
        int l;
        int r;
        ll sum;
        ll lazy;        //lazy标记
    }node[maxn << 2];
    
    void pushup(int rt)
    {
        node[rt].sum = node[rt << 1].sum + node[rt << 1 | 1].sum;
    }
    
    void pushdown(int rt , int nl , int nr)
    {
        //rt指当前节点,,,
        //nl指左节点有nl个需要被赋值为lazy
        //同理,,nr指右节点有nr个需要被赋值为lazy
        if(node[rt].lazy)
        {
            //当这节点lazy不为0时,,要向下更新一下
            node[rt << 1].sum = node[rt].lazy * nl; //修改sum
            node[rt << 1].lazy = node[rt].lazy; //下推lazy
    
            node[rt << 1 | 1].sum = node[rt].lazy * nr;
            node[rt << 1 | 1].lazy = node[rt].lazy;
    
            node[rt].lazy = 0;      //标记清除
        }
    }
    
    void build(int rt , int l , int r)
    {
        node[rt].l = l;
        node[rt].r = r;
        node[rt].sum = 0;
        node[rt].lazy = 0;      //不要忘了
    
        if(l == r)
        {
            node[rt].sum = 1;
            return;
        }
    
        int mid = node[rt].l + ((node[rt].r - node[rt].l) >> 1);
    
        build(rt << 1 , l , mid);
        build(rt << 1 | 1 , mid + 1 , r);
    
        pushup(rt);
    
        return;
    }
    void update(int rt , int L , int R , int C)
    {
        if(L <= node[rt].l && node[rt].r <= R)
        {
            //当该节点对应的区间在所要操作的区间里时更新
            node[rt].sum = (node[rt].r - node[rt].l + 1) * C;
            node[rt].lazy = C;
            return;
        }
    
        int mid = node[rt].l + ((node[rt].r - node[rt].l) >> 1);
        //下推lazy标记,,想上保证正确
        pushdown(rt , mid - node[rt].l + 1 , node[rt].r - mid);
    
        if(L <= mid)    update(rt << 1 , L , R , C);
        if(R >  mid)    update(rt << 1 | 1 , L , R , C);
        pushup(rt);
        return;
    }
    ll query(int rt , int L , int R)
    {
        if(L <= node[rt].l && node[rt].r <= R)
        {
            return node[rt].sum;
        }
    
        int mid = node[rt].l + ((node[rt].r - node[rt].l) >> 1);
    
        pushdown(rt , mid - node[rt].l + 1 , node[rt].r - mid);
    
        ll ans = 0;
        if(L <= mid)    ans += query(rt << 1 , L , R);
        if(R >  mid)    ans += query(rt << 1 | 1 , L , R);
        return ans;
    }
    int main(int argc, char const *argv[])
    {
        int T;scanf("%d" , &T);
        for(int i = 1; i <= T; ++i)
        {
            int n , q;
            scanf("%d%d" , &n , &q);
    
            build(1 , 1 , n);
    
            while(q--)
            {
                int a , b , c;
                scanf("%d%d%d" , &a , &b , &c);
    
                update(1 , a , b , c);
            }
    
            printf("Case %d: The total value of the hook is %lld.
    " , i , query(1 , 1 , n));
        }
        return 0;
    }
    

    大概就是这么多,,,只要理解了lazy的作用,,,以及下推的意思,,,基本就ok了,,,,

    (end)

    剑之所指,心之所向,身之所往!!!
  • 相关阅读:
    「系统集成方案」智慧工地
    「Django」学习之路,持续更改
    「Django」与mysql8连接的若干问题
    「Python」socket指南
    「Python」35个知识点
    「CSS」文本编排相关的CSS属性设置
    「CSS」css基础
    bWAPP----HTML Injection
    bWAPP----HTML Injection
    bWAPP----HTML Injection
  • 原文地址:https://www.cnblogs.com/31415926535x/p/9768560.html
Copyright © 2011-2022 走看看