• 线段树总结


    今天学习线段树,有一些感悟。

    第一,要想清楚pushdown和pushup的用处:

    一个是将u的信息传递给子节点,一个是将子节点的信息传递给父亲节点。

    第二,建树的判定:

    当left和right相等时,赋值成输入的a[u],然后return,完成部分的建树。

    第三,更新时要分3种情况:

    其一是所要更新的区间全部在s[u].l到mid时,直接在L(u)继续向下找,这里要注意,所找的区间还是left到right,跟mid无关。

    其二是所要更新的区间全部在mid到s[u].r时,在R(u)继续向下找,这里也要注意,所找的区间还是left到right。

    其三是所要更新的区间在两边都有交集时,要分两边找,这里要注意:所找的区间就是left到mid和mid+1到right了。千万不能写错!(调了很久才发现。⊙﹏⊙b汗)

    第四,结构体:

    结构体内定义left,right表示s[u]区间的两端,其他变量由题意定义。(例如sum,height,add,price等)结构体外的数组一般定成4*MAXN那么大就可以了。

    第五:格式:

    一定要看清题目的输入格式和输出格式!有些题输入是多组数据,还有输出时一般情况要换行。

    下面是线段树的一些基本框架:

    1.建树:

    void Build (int u,int left,int right)//u表当前结点
     { //left right 表左区间范围[left,right]
        node[u].l = left,node[u].r = right;
        …..                              //结点信息的初始化
        if (node[u].l == node[u].r)     //到叶结点 return
        {
            ……                         //某些赋值
            return ;
        }
        int mid = (node[u].l + node[u].r)>>1;
        Build (L(u),left,mid);
        Build (R(u),mid+1,right);
    }
     2.更新:
    void Update(int u,int left,int right,data val)
    {
        if (left<=node[u].l&&node[u].r <= right){
            ……..               //进行某些更改操作
            return ;
        }
         Pushdown(u);          // 成段更新时,这里一般都有个延时更新
        int mid = (node[u].l + node[u].r)>>1;   //然后就是往左 往右 或左右找区间 几乎所有的
        if (right <= mid) Update(L(u),left,right,val);             //线段树都这样
        else if (left > mid) Update(R(u),left,right,val);
        else {
            Update(L(u),left,mid,val);
            Update(R(u),mid+1,right,val);
        }
        Pushup(u);        //这里也一般有个向上更新
    }
     3.查询:
    int Query(int u,int left,int right)
    {
        if (left <= node[u].l&&node[u].r <= right)
            return node[u].sum;
        Pushdown(u);    //同update操作 视情况可有可无
        int mid = (node[u].l + node[u].r)>>1;
        if (right <= mid) return Query(L(u),left,right);
        else if (left > mid) return Query(R(u),left,right);
        else return (Query(L(u),left,mid) + Query(R(u),mid+1,right));
        Pushup(u);       //
    }
     4.向上回溯:
    void Pushup(int u)
    {
        node[u].sum = node[L(u)].sum + node[R(u)].sum;
        …….
        …….
        return ;
    }
     5.延时更新(向下更改):
    void Pushdown (int u)   //延迟覆盖操作
    {
        if (node[u].state == -1) {
          更新父结点,左右子结点信息
        }
        else if (node[u].state == 1){
                更新父结点,左右子结点信息
        }
        else {
    ………
    }
    }
     
     
  • 相关阅读:
    C/C++编程可用的Linux自带工具
    安装gcc及其依赖
    Linux上编译hadoop-2.7.1的libhdfs.so和libhdfs.a
    gcc链接参数--whole-archive的作用
    jdb调试程序
    Exception in thread "main" java.lang.Error: Unresolved compilation problem
    动态规划与分治、备忘录的区别
    leetcode-unique paths
    LeetCode总结 -- 一维动态规划篇
    编程技巧
  • 原文地址:https://www.cnblogs.com/937337156Zhang/p/5667653.html
Copyright © 2020-2023  润新知