hiho上的一些线段树问题总结

概念:线段树(Segment Tree)是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。对于线段树中的每一个非叶子节点[a,b],它的左子树表示的区间为[a,(a+b)/2],右子树表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树。叶节点数目为N,即整个线段区间的长度。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。——摘自维基百科

基本思路:把每个待处理的区间都拓展到完全二叉树最后一层的节点个数,形成完全二叉树,对于节点o,其左右子节点分别为o*2,o*2+1,叶子节点就是单个节点形成的区间,使用数组维护二叉树(简单高效)。

下面是在hiho oj网站涉及的所有线段树的题目及分析

点修改

Hiho18 :返回区间最小值

思路:使用数组minv[i]维护结点编号为i的结点区间的最小值.

  • 查询操作:

结点的区间在查询区间内则直接返回结点对应最小值minv[o],否则分别对结点的左右子树查询相应最小值,然后取左右子树的较小值作为最小值。

  • 修改操作:

主要是针对修改结点涉及的区间对应结点的最小值信息进行维护。

区间修改

Hiho20:区间修改(只设置),返回区间和

思路:使用数组setv[i]维护区间设置的值,setv[o]>=0表明在o结点区间内的值都是setv[o],setv[o]=-1表明o所在区间的值不尽相同或者此区间没有数值。

  • 查询操作:

如果setv[o]>=0则直接n*setv[o]计算到sum中,否则进入o的子节点计算在查询区间的和。

  • 修改操作:

如果结点区间在修改区间内,则直接setv[o]=v,否则对子节点的在修改区间的结点赋值,同时如果setv[o]>0则要将该值传递给子节点,同时该节点的
setv[o]变为-1(因为该区间数值出现了不一致)。

Hiho21:连续区间离散化

思路:在这道题目是通过线段树结点将连续型区间离散化,并且将连续区间归一化,减少空间复杂度(预处理详见题目链接提示部分),然后进行区间修改,之后的算法同hiho20,只是需要考虑连续区间进行分解时比较特殊:

离散型:区间[l,r]分解为[l,m] [m+1,r]

连续性:区间[l,r]分解为[l,m] [m,r]

hiho22:设置为某一值或增加一个增量(正负都可),返回总量

这里用了数组setv和sumv来维护区间值和区间和。所以查询操作直接返回sumv的第一个结点值就是总量,时间复杂度为O(1),对于两种修改操作首先明确:sumv[o] = sumv[2*o]+sumv[2*o+1].

  • set型修改操作

和前面hiho20的基本一致,只是这里要同时维护sumv的信息。如果结点区间在修改区间,setv[o]=v并且sumv[o]做更新,否则在处理完子节点后使用
sumv[o] = sumv[2*o]+sumv[2*o+1]更新o结点

  • add型修改操作

逻辑和set型基本一致,需要另外考虑的有两点,一是setv[o] += v时需要考虑是否超过题目要求的值的最小或最大值并作相应处理;二是add型操作在结点
的区间在修改区间内的情况下,如果setv[o]==-1,需要继续访问子节点知道找到setv[o]>=0时才能去更新setv[o]和sumv[o].

注:这四道题代码请参见我的github账号的leetcode仓库下。

总结

好多题目基本逻辑理解不难,但是要考虑周全并accept并不容易,主要是有些地方考虑不周。所以在提交代码前除了示例正确外可以认真考虑测试几个有代表性的测试用例,这样可以保证更高的通过率。

时间: 2024-10-08 08:37:26

hiho上的一些线段树问题总结的相关文章

hiho一下20周 线段树的区间修改

线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格--小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问--小Hi给出一段区间[L, R]

hiho 1169(猜数字-线段树求min(|Ai-k|))

#1169 : 猜数字 时间限制:10000ms 单点时限:5000ms 内存限制:256MB 描述 你正在和小冰玩一个猜数字的游戏.小冰首先生成一个长为N的整数序列A1, A2, -, AN.在每一轮游戏中,小冰会给出一个区间范围[L, R],然后你要猜一个数K.如果K在AL, AL+1, -, AR中,那么你获胜. 在尝试了几轮之后,你发现这个游戏太难(无聊)了.小冰决定给你一些提示,你每猜一次,小冰会告诉你K与AL, AL+1, -, AR中最接近的数的绝对差值,即min(|Ai - K|

树链剖分(以维护线段树为例)

关于树链剖分的有关知识:http://www.cnblogs.com/sagitta/p/5660749.html 以下是洛谷p3384经过无数次WA和RE(最后发现只是有一个函数的调用写反了qwq)终于AC的代码: #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<climits> #in

树——用二叉树构建线段树

上一博文线段树问题中,用数组表示线段树,成功AC了,本文用二叉树表示线段树,复习一下二叉树,不过下面这段用二叉树代码表示的线段树是无法AC的,因为这个代码的空间复杂度远高于上一个用结构体数组表示的空间复杂度. #include<iostream> #include<cstdlib> #include<algorithm> #include<vector> #include<list> #include<iterator> #inclu

线段树之入门篇

线段树(interval tree) 是把区间逐次二分得到的一树状结构,它反映了包括归并排序在内的很多分治算法的问题求解方式. 上图是一棵典型的线段树,它对区间[1,10]进行分割,直到单个点.这棵树的特点 是: 1. 每一层都是区间[a, b]的一个划分,记 L = b - a 2. 一共有log2L层 3. 给定一个点p,从根到叶子p上的所有区间都包含点p,且其他区间都不包含点p. 4. 给定一个区间[l; r],可以把它分解为不超过2log2 L条不相交线段的并. 其中第四点并不是很显然,

&#183;专题」 线段树

PKU暑期培训第一天,这次培训人很多,但是感觉打酱油的也不少,不知道大牛有多少. 第一天都是讲线段树的,课件的话和往常一样,没什么变化. 具体的话,讲了线段树和树状数组.线段树的话讲了单点更新,成段更新,扫描线已经离散化. 然后随便提了提树状数组.估计明天再讲一点点,然后接着是讲并查集,多串匹配什么的. 线段树的题目我做得很少,以前看过HH大神的模板,想模仿来着,其实也没什么理解. 重新理解一下线段树吧. 线段树的用途,主要是维护区间问题,比如区间的单点更新操作,成段更新,扫描线等等.当然还有一

【BZOJ-4592】脑洞治疗仪 线段树

4592: [Shoi2015]脑洞治疗仪 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 69  Solved: 38[Submit][Status][Discuss] Description 曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个01序列.1代表这个位置的脑组织正常工作,0代表这是一块脑洞. 1 0 1 0 0 0 1 1 1

【hihoCoder】第20周 线段树

题目: 输入 每个测试点(输入文件)有且仅有一组测试数据. 每组测试数据的第1行为一个整数N,意义如前文所述. 每组测试数据的第2行为N个整数,分别描述每种商品的重量,其中第i个整数表示标号为i的商品的重量Pi. 每组测试数据的第3行为一个整数Q,表示小Hi进行的操作数. 每组测试数据的第N+4~N+Q+3行,每行分别描述一次操作,每行的开头均为一个属于0或1的数字,分别表示该行描述一个询问和一次商品的价格的更改两种情况.对于第N+i+3行,如果该行描述一个询问,则接下来为两个整数Li, Ri,

poj 2482 Stars in Your Window (线段树:区间更新)

题目链接:http://poj.org/problem?id=2482 读完题干不免有些心酸(??????) 题意:有n个星星(星星i的坐标为xi, yi,亮度为ci),给你一个W*H的矩形,让你求得矩形能覆盖的星星的亮度和最大为多少 思路:矩形大小是固定的,所以可以换个方向思考,把矩形看成一个点(坐标为矩形中心),每个星星的影响区间范围为W*H的矩形(星星原来的坐标为矩形中心),该区间的亮度增加c.该问题就变成了求哪个点的亮度最大.坐标范围太大,直接暴力枚举不可能,所以需要预先进行离散化.在纵