当前位置:网站首页>【每日一题】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); */
边栏推荐
- [brush questions] how can we correctly meet the interview?
- 26岁从财务转行软件测试,4年沉淀我已经是25k的测开工程师...
- 成功解决AttributeError: Can only use .cat accessor with a ‘category‘ dtype
- What is the difference between int (1) and int (10)? Senior developers can't tell!
- How much is the price for the seal of the certificate
- Leetcode daily question (1997. first day where you have been in all the rooms)
- SAP SD发货流程中托盘的管理
- On the first day of clock in, click to open a surprise, and the switch statement is explained in detail
- 如何做好金融文献翻译?
- What are the commonly used English words and sentences about COVID-19?
猜你喜欢
![[English] Grammar remodeling: the core framework of English Learning -- English rabbit learning notes (1)](/img/02/41dcdcc6e8f12d76b9c1ef838af97d.png)
[English] Grammar remodeling: the core framework of English Learning -- English rabbit learning notes (1)

同事上了个厕所,我帮产品妹子轻松完成BI数据产品顺便得到奶茶奖励

翻译生物医学说明书,英译中怎样效果佳

【刷题】怎么样才能正确的迎接面试?

How effective is the Chinese-English translation of international economic and trade contracts

Lesson 7 tensorflow realizes convolutional neural network

CS通过(CDN+证书)powershell上线详细版

字幕翻译中翻英一分钟多少钱?

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

A method to measure the similarity of time series: from Euclidean distance to DTW and its variants
随机推荐
Day 239/300 注册密码长度为8~14个字母数字以及标点符号至少包含2种校验
AttributeError: Can‘t get attribute ‘SPPF‘ on <module ‘models.common‘ from ‘/home/yolov5/models/comm
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
【软件测试进阶第1步】自动化测试基础知识
Basic commands of MySQL
Day 248/300 thoughts on how graduates find jobs
字幕翻译中翻英一分钟多少钱?
AttributeError: Can‘t get attribute ‘SPPF‘ on <module ‘models. common‘ from ‘/home/yolov5/models/comm
Call, apply, bind rewrite, easy to understand with comments
[unity] how to export FBX in untiy
Difference between backtracking and recursion
Is it difficult for girls to learn software testing? The threshold for entry is low, and learning is relatively simple
Biomedical English contract translation, characteristics of Vocabulary Translation
Office-DOC加载宏-上线CS
利用快捷方式-LNK-上线CS
Leetcode daily question (1870. minimum speed to arrive on time)
Do you really know the use of idea?
After working for 10 years, I changed to a programmer. Now I'm 35 + years old and I'm not anxious
UniPro甘特图“初体验”:关注细节背后的多场景探索
翻译生物医学说明书,英译中怎样效果佳