• 线段树学习(一)


      看到UESTC的数据结构专题快要结束了,感觉自己真心浪费了好多时间,没有像鑫航学姐那样叮嘱的一样,紧紧的跟住训练。

    所以下决心认认真真的开始学习下线段树的知识,以前对于线段树的学习都是一知半解的,就是说,我只知道线段树是用来单点更新和区间查值的,其实,线段树的功能远远不止这些。

      先来说下,线段树是用来求解有关区间问题的绝逼法宝,为什么说绝逼呢。因为它能够在logn的时间内完成每次的查询。

    查询的分类:

      1.区间查询

      -访问某段区间的某些性质(比如说,最大值,最小值,连续和,等等)

      2.区间更新

      -某些操作影响了某段区间(比如说,统一加一个值)

    归于以上两个查询,我们总结出了线段树能够解决的以下三个问题.

      -更新点,查询区间

      -更新区间,查询点

      -更新区间,查询区间

    要想深入的理解线段树,我们从一个比较经典的例子开始了解吧。

    我现在有一个长度为 n的一维数组(a[1]~a[n])

    我们每次对这个数组只允许有以下的操作:

    ~1.修改数组中某个元素的值

       - [1,5,4,1,6]  ---(a[2] = 3)---[1,3,4,1,6]

    ~2.询问数组中某段区间的最大值

       -[1,5,4,1,6]   ---(max(1,4)=?) ---> 5

    ~3.询问数组中某段区间的和

     -[1,5,4,1,6]  ---(sum(3,5)=?) ---> 11

      在没有知道线段树之前,我们知道,要对一个数组进行这样的操作是很简单的每次只要O(n)的时间扫一遍就是可以得到各种询问的ans的。

    那么,如果我要进行Q次询问该怎么办呢?这样的话就变成了O(nQ)的复杂度了,,擦,,这也太慢了吧,随便给你一组数据,你就T了

    所以,为了在更快的时间里解决这些查询问题,我们引入了一个叫做线段树的数据结构,线段树就是一个能在logn的时间内完成每次操作。

    线段树的本质是一棵二叉树,不同于一般的二叉树来说,线段树的每个节点维护的都是一段区间的信息。

    比如下面这个二叉树,对于一个长度为5的数组a[1]~a[5]

           [1,.5]

        [1,3]      [4,5]

      [1,2]   [3,3]   [4,4]  [5,5]                          对于这个树的构建有几点说明,对于任意一个非叶子节点来说,如果它所维护的区间是[l,r]的话,它的左儿子区

    [1,1]   [2,2]                间就是[l,(l+r)/2], 右儿子区间就是[(l+r)/2+1,r];

    线段树      ---实现

    每个节点记录的信息

    1 struct Segtree
    2 {
    3     int left,right;//区间的端点
    4     int mx,mn;//区间内的最大值和最小值
    5     int sum;//区间内元素的总和
    6 }tree[MAX*4];

      我们先用一个数组a[]来记录节点,并且根节点的下标为1,然后,对于任意一个节点来说a[k]来说,他的左儿子是a[k<<1],右儿子是a[k<<1|1]

    建立一棵线段树代码实现

    void build ( int id,int l,int r )
    {
        tree[id].left = l; tree[id].right = r;
        if ( l==r )
        {
            tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum;
            tree[id].mx = max(tree[id<<1].mx,tree[id<<1|1].mx);
            tree[id].mn = min(tree[id<<1].mn,tree[id<<1|1].mn);
        }
        else
        {
            int mid = (l+r)>>1;
            build(id<<1,l,mid);
            build(id<<1|1,mid+1,r);
            tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum;
            tree[id].mx = max(tree[id<<1].mx,tree[id<<1|1].mx);
            tree[id].mn = min(tree[id<<1].,mn,tree[id<<1|1].mn);
        }
    }
  • 相关阅读:
    扯一下关于魔兽改键的蛋
    Emacs23.3在ubuntu10.10下的手动编译与安装
    GRUB2英文文档的部分翻译
    WinForm中Crossthread operation not valid错误的解决方法
    C# 嵌入式资源
    raster配准
    excel vba 玫瑰图 风速 风向
    使用UserControl好处
    How does ArcSDE use Oracle Spatial? arcsde怎么使用oracle spatial
    信息抽取的定义(definition of information extraction)
  • 原文地址:https://www.cnblogs.com/wikioibai/p/4452177.html
Copyright © 2020-2023  润新知