当前位置:网站首页>【每日一题】729. 我的日程安排表 I
【每日一题】729. 我的日程安排表 I
2022-07-06 06:42:00 【王六六的IT日常】
729. 我的日程安排表 I

参考:大佬在力扣题解写的博文-----线段树详解「汇总级别整理 」
线段树系列:
线段树解决的是「区间和」的问题,且该「区间」会被修改。
举个简单的,对于 nums = [1, 2, 3, 4, 5]。
如果我们需要多次求某一个区间的和,是不是首先想到了利用「前缀和」。
关于前缀和的详细介绍可见 前缀和数组
nums = [1, 2, 3, 4, 5] 对应的线段树如下所示:
每个节点代表一个区间,而节点的值就是该区间的和。
- 数字之和「总数字之和 = 左区间数字之和 + 右区间数字之和」
- 最大公因数 (GCD)「总 GCD = gcd(左区间 GCD, 右区间 GCD)」
- 最大值「总最大值 = max(左区间最大值,右区间最大值)」
线段树的数据结构
我们可以使用数组来表示一棵线段树,假如根节点为 i,那么左孩子的节点就为 2 * i,右孩子的节点就为 2 * i + 1 (前提:i 从 1 开始)
我们可以使用链表来表示一棵线段树,其节点的数据结构如下:
class Node {
// 左右孩子节点
Node left, right;
// 当前节点值
int val;
}
比较倾向使用链表,因为比较节约内存,下面的实现均基于链表。
线段树的建立
如果题目中给了具体的区间范围,我们根据该范围建立线段树。
public void buildTree(Node node, int start, int end) {
// 到达叶子节点
if (start == end) {
node.val = arr[start];
return ;
}
int mid = (start + end) >> 1;
buildTree(node.left, start, mid);
buildTree(node.right, mid + 1, end);
// 向上更新
pushUp(node);
}
// 向上更新
private void pushUp(Node node) {
node.val = node.left.val + node.right.val;
}
但是很多时候,题目中都没有给出很具体的范围,只有数据的取值范围,一般都很大,所以我们更常用的是「动态开点」。
「动态开点」一般是在「更新」或「查询」的时候动态的建立节点,具体可见下面的更新和查询操作。
线段树完整模版
注意:下面模版基于求「区间和」以及对区间进行「加减」的更新操作,且为「动态开点」
/** * @Description: 线段树(动态开点) * @Author: LFool * @Date 2022/6/7 09:15 **/
public class SegmentTreeDynamic {
class Node {
Node left, right;
int val, add;
}
private int N = (int) 1e9;
private Node root = new Node();
public void update(Node node, int start, int end, int l, int r, int val) {
if (l <= start && end <= r) {
node.val += (end - start + 1) * val;
node.add += val;
return ;
}
int mid = (start + end) >> 1;
pushDown(node, mid - start + 1, end - mid);
if (l <= mid) update(node.left, start, mid, l, r, val);
if (r > mid) update(node.right, mid + 1, end, l, r, val);
pushUp(node);
}
public int query(Node node, int start, int end, int l, int r) {
if (l <= start && end <= r) return node.val;
int mid = (start + end) >> 1, ans = 0;
pushDown(node, mid - start + 1, end - mid);
if (l <= mid) ans += query(node.left, start, mid, l, r);
if (r > mid) ans += query(node.right, mid + 1, end, l, r);
return ans;
}
private void pushUp(Node node) {
node.val = node.left.val + node.right.val;
}
private void pushDown(Node node, int leftNum, int rightNum) {
if (node.left == null) node.left = new Node();
if (node.right == null) node.right = new Node();
if (node.add == 0) return ;
node.left.val += node.add * leftNum;
node.right.val += node.add * rightNum;
// 对区间进行「加减」的更新操作,下推懒惰标记时需要累加起来,不能直接覆盖
node.left.add += node.add;
node.right.add += node.add;
node.add = 0;
}
}
class MyCalendar {
public MyCalendar() {
}
public boolean book(int start, int end) {
// 先查询该区间是否为 0
if (query(root, 0, N, start, end - 1) != 0) return false;
// 更新该区间
update(root, 0, N, start, end - 1, 1);
return true;
}
// *************** 下面是模版 ***************
class Node {
// 左右孩子节点
Node left, right;
// 当前节点值,以及懒惰标记的值
int val, add;
}
private int N = (int) 1e9;
private Node root = new Node();
public void update(Node node, int start, int end, int l, int r, int val) {
if (l <= start && end <= r) {
node.val += val;
node.add += val;
return ;
}
pushDown(node);
int mid = (start + end) >> 1;
if (l <= mid) update(node.left, start, mid, l, r, val);
if (r > mid) update(node.right, mid + 1, end, l, r, val);
pushUp(node);
}
public int query(Node node, int start, int end, int l, int r) {
if (l <= start && end <= r) return node.val;
pushDown(node);
int mid = (start + end) >> 1, ans = 0;
if (l <= mid) ans = query(node.left, start, mid, l, r);
if (r > mid) ans = Math.max(ans, query(node.right, mid + 1, end, l, r));
return ans;
}
private void pushUp(Node node) {
// 每个节点存的是当前区间的最大值
node.val = Math.max(node.left.val, node.right.val);
}
private void pushDown(Node node) {
if (node.left == null) node.left = new Node();
if (node.right == null) node.right = new Node();
if (node.add == 0) return ;
node.left.val += node.add;
node.right.val += node.add;
node.left.add += node.add;
node.right.add += node.add;
node.add = 0;
}
}
/** * Your MyCalendar object will be instantiated and called as such: * MyCalendar obj = new MyCalendar(); * boolean param_1 = obj.book(start,end); */
边栏推荐
- Latex文字加颜色的三种办法
- Address bar parameter transmission of list page based on jeecg-boot
- Apache DolphinScheduler源码分析(超详细)
- Advanced MySQL: Basics (1-4 Lectures)
- 机器学习植物叶片识别
- The ECU of 21 Audi q5l 45tfsi brushes is upgraded to master special adjustment, and the horsepower is safely and stably increased to 305 horsepower
- 电子书-CHM-上线CS
- How much is it to translate Chinese into English for one minute?
- Day 248/300 关于毕业生如何找工作的思考
- Office-DOC加载宏-上线CS
猜你喜欢

翻译影视剧字幕,这些特点务必要了解

我的创作纪念日

AttributeError: Can‘t get attribute ‘SPPF‘ on <module ‘models. common‘ from ‘/home/yolov5/models/comm

CS-证书指纹修改

万丈高楼平地起,每个API皆根基

基于购买行为数据对超市顾客进行市场细分(RFM模型)

电子书-CHM-上线CS

金融德语翻译,北京专业的翻译公司

SQL Server Manager studio (SSMS) installation tutorial

At the age of 26, I changed my career from finance to software testing. After four years of precipitation, I have been a 25K Test Development Engineer
随机推荐
Difference between backtracking and recursion
[ 英語 ] 語法重塑 之 動詞分類 —— 英語兔學習筆記(2)
AttributeError: Can‘t get attribute ‘SPPF‘ on <module ‘models. common‘ from ‘/home/yolov5/models/comm
ML之shap:基于adult人口普查收入二分类预测数据集(预测年收入是否超过50k)利用Shap值对XGBoost模型实现可解释性案例之详细攻略
Wish Dragon Boat Festival is happy
Fedora/rehl installation semanage
The ECU of 21 Audi q5l 45tfsi brushes is upgraded to master special adjustment, and the horsepower is safely and stably increased to 305 horsepower
Machine learning plant leaf recognition
【软件测试进阶第1步】自动化测试基础知识
L'Ia dans les nuages rend la recherche géoscientifique plus facile
How to translate biomedical instructions in English
Erreur de type résolue avec succès: type de données « catégorie» non sous - jacente
Redis Foundation
Making interactive page of "left tree and right table" based on jeecg-boot
MySQL high frequency interview 20 questions, necessary (important)
After working for 10 years, I changed to a programmer. Now I'm 35 + years old and I'm not anxious
Simple use of MySQL database: add, delete, modify and query
E-book CHM online CS
Day 246/300 SSH connection prompt "remote host identification has changed!"
中英对照:You can do this. Best of luck祝你好运