线段树学习(一)

  看到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);
    }
}
时间: 2024-11-11 17:05:34

线段树学习(一)的相关文章

线段树学习笔记

线段树学习笔记 20180112 http://www.cnblogs.com/wuyuanyuan/p/8277100.html 一定要明确需要维护的值(区间最大值.区间和--). 原文地址:https://www.cnblogs.com/wuyuanyuan/p/8278004.html

线段树学习

此题题意很好懂:  给你N个数,Q个操作,操作有两种,‘Q a b ’是询问a~b这段数的和,‘C a b c’是把a~b这段数都加上c. 需要用到线段树的,update:成段增减,query:区间求和 介绍Lazy思想:lazy-tag思想,记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率. 在此通俗的解释我理解的Lazy意思,比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果

线段树--数据结构专题学习

这两周是数据结构专题的学习,,被专题的题目虐得死去活来== 线段树:简单的说就是把[1,n]的区间二分,[1,(1+n)/2]左子树,[(1+n)/2+1,n]右子树 就这样一直分下去,直到都是[x,x]这样的区间.这样就构成了一颗树了^-^ 有这样一棵树,我们就可以在节点中储存区间的和啊,区间内的最大值啊,最小值等等..这就是线段树的附加信息了,也是题目中的重点.. 我们可以用一个数组(长度为k)储存原区间的初始值,然后根据这个建树,所以这个树的节点数最多为4*K: 对于每个节点i,其左子树为

ACM学习历程—HDU 5023 A Corrupt Mayor&#39;s Performance Art(广州赛区网赛)(线段树)

Problem Description Corrupt governors always find ways to get dirty money. Paint something, then sell the worthless painting at a high price to someone who wants to bribe him/her on an auction, this seemed a safe way for mayor X to make money. Becaus

算法学习——动态图连通性(线段树分治+按秩合并并查集)

在考场上遇到了这个的板子题,,,所以来学习了一下线段树分治 + 带撤销的并查集. 题目大意是这样的:有m个时刻,每个时刻有一个加边or撤销一条边的操作,保证操作合法,没有重边自环,每次操作后输出当前图下所有联通块大小的乘积. 首先观察到如果没有撤销操作,那么直接用并查集就可以维护,每次合并的时候乘上要合并的两个并查集大小的逆元,然后乘上合并之后的大小即可. 那么来考虑撤销,观察到如果并查集不带路径压缩,应该是可以处理撤销操作的. 但我们并不能直接做,因为并查集的撤销必须按顺序来,就相当于每次合并

HDU 1540(线段树+区间合并)学习记录

学习了线段树的新姿势,记录一下 参考blog:https://blog.csdn.net/sunyutian1998/article/details/79618316 query的时候m-ql+1和qr-m写成了m-l+1.r-m,wa了几发之后才找到bug 错误样例: 10 1Q 5 wrong answer:5 顺带一提,这个题目可以在set上面二分直接过,不过最主要还是为了练习区间合并 #include<bits/stdc++.h> using namespace std; const

ACM学习历程——HDU2227 Find the nondecreasing subsequences(线段树 &amp;&amp; dp)

Description How many nondecreasing subsequences can you find in the sequence S = {s1, s2, s3, ...., sn} ? For example, we assume that S = {1, 2, 3}, and you can find seven nondecreasing subsequences, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}.

ACM学习历程——POJ3321 Apple Tree(搜索,线段树)

      Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree. The tree has N forks which are connected by bran

ACM学习历程——POJ3468 A Simple Problem with Integers(线段树)

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. In