[英雄星球六月集训LeetCode解题日报] 第22日 有序集合
日报
- 刚写的珂朵莉板子,没想到这么快就用上了。
- 1、3题用的珂朵莉。
- 注意这俩题其实都没有大范围assign,正解大概都不应该是珂朵莉,不过反正过了。
题目
一、 732. 我的日程安排表 III
链接: 732. 我的日程安排表 III
1. 题目描述
当 k 个日程安排有一些时间上的交叉时(例如 k 个日程安排都在同一时间内),就会产生 k 次预订。
给你一些日程安排 [start, end) ,请你在每个日程安排添加后,返回一个整数 k ,表示所有先前日程安排会产生的最大 k 次预订。
实现一个 MyCalendarThree 类来存放你的日程安排,你可以一直添加新的日程安排。
MyCalendarThree() 初始化对象。
int book(int start, int end) 返回一个整数 k ,表示日历中存在的 k 次预订的最大值。
2. 思路分析
这题的兄弟三题在我的笔记里用过很多次,动态开点线段树套的最快。
但珂朵莉能做!比线段树快!
优化完比官解还快!这很柯学!

3. 代码实现
class ODTNode:
def __init__(self,l,r,v):
self.l,self.r,self.v = l,r,v
def __lt__(self,other):
return self.l<other.l
def jiebao(self):
return self.l,self.r,self.v
class ODT:
def __init__(self,l,r,v):
from sortedcontainers import SortedList
self.tree = SortedList([ODTNode(l,r,v)])
def split(self,pos):
""" 在pos位置切分,返回左边界l为pos的线段下标
"""
tree = self.tree
p = tree.bisect_left(ODTNode(pos,0,0))
if p != len(tree) and tree[p].l == pos:
return p
p -= 1
l,r,v = tree[p].jiebao()
tree[p].r = pos-1
# tree.pop(p)
# tree.add(ODTNode(l,pos-1,v))
tree.add(ODTNode(pos,r,v))
return p+1
def assign(self,l,r,v):
"""
把[l,r]区域全变成val
"""
tree = self.tree
begin = self.split(l)
end = self.split(r+1)
for i in range(begin,end):
tree.pop(begin)
tree.add(ODTNode(l,r,v))
# 以下操作全是暴力,寄希望于这里边元素不多。
def add_interval(self,l,r,val):
"""区间挨个加
"""
tree = self.tree
begin = self.split(l)
end = self.split(r+1)
m = 0
for i in range(begin,end):
tree[i].v += val
m = max(m,tree[i].v)
return m
def query_max(self,l,r):
"""
查找x,y区间的最大值
"""
begin = self.split(l)
end = self.split(r+1)
return max(node.v for node in self.tree[begin:end])
def query_all_max(self,):
"""
查找x,y区间的最大值
"""
begin = self.split(0)
end = self.split(10**9+1)
return max(node.v for node in self.tree[begin:end])
class MyCalendarThree:
def __init__(self):
self.odt = ODT(0,10**9,0)
self.m = 0
def book(self, start: int, end: int) -> int:
self.m = max(self.m,self.odt.add_interval(start,end-1,1))
return self.m
# return self.odt.query_all_max()
二、 895. 最大频率栈
链接: 895. 最大频率栈
1. 题目描述
设计一个类似堆栈的数据结构,将元素推入堆栈,并从堆栈中弹出出现频率最高的元素。
实现 FreqStack 类:
- FreqStack() 构造一个空的堆栈。
- void push(int val) 将一个整数 val 压入栈顶。
- int pop() 删除并返回堆栈中出现频率最高的元素。
- 如果出现频率最高的元素不只一个,则移除并返回最接近栈顶的元素。
2. 思路分析
没想到什么好办法,硬做。
- cnt储存每个数的计数;max_f储存当前最大频率是几;f_x储存每个频率经过的数字,用哈希表储存栈
- 入栈时,计数+1,频率更新,这个数的新频率栈入栈。
- 出栈时,检查当前最大频率对应的栈是否空,空的话降低到非空那个,然后出栈,更新频率。
3. 代码实现
class FreqStack:
def __init__(self):
self.cnt = Counter()
self.f_x = defaultdict(list)
self.max_f = 0
def push(self, val: int) -> None:
cnt = self.cnt
cnt[val] +=1
self.max_f = max(self.max_f,cnt[val])
self.f_x[cnt[val]].append(val)
def pop(self) -> int:
f_x = self.f_x
while not f_x[self.max_f]:
self.max_f -=1
x = f_x[self.max_f].pop()
self.cnt[x] -= 1
return x
三、 352. 将数据流变为多个不相交区间
1. 题目描述

2. 思路分析
用数组映射一下,这就是个简单的线段合并。
我就是要用柯学做!
回头有空用数组写一下看看。
3. 代码实现
class ODTNode:
def __init__(self,l,r,v):
self.l,self.r,self.v = l,r,v
def __lt__(self,other):
return self.l<other.l
def jiebao(self):
return self.l,self.r,self.v
class ODT:
def __init__(self,l,r,v):
from sortedcontainers import SortedList
self.tree = SortedList([ODTNode(l,r,v)])
def split(self,pos):
""" 在pos位置切分,返回左边界l为pos的线段下标
"""
tree = self.tree
p = tree.bisect_left(ODTNode(pos,0,0))
if p != len(tree) and tree[p].l == pos:
return p
p -= 1
l,r,v = tree[p].jiebao()
tree[p].r = pos-1
# tree.pop(p)
# tree.add(ODTNode(l,pos-1,v))
tree.add(ODTNode(pos,r,v))
return p+1
def assign(self,l,r,v):
"""
把[l,r]区域全变成val
"""
tree = self.tree
begin = self.split(l)
end = self.split(r+1)
for i in range(begin,end):
tree.pop(begin)
tree.add(ODTNode(l,r,v))
# 以下操作全是暴力,寄希望于这里边元素不多。
def add_interval(self,l,r,val):
"""区间挨个加
"""
tree = self.tree
begin = self.split(l)
end = self.split(r+1)
m = 0
for i in range(begin,end):
tree[i].v += val
m = max(m,tree[i].v)
return m
def query_max(self,l,r):
"""
查找x,y区间的最大值
"""
begin = self.split(l)
end = self.split(r+1)
return max(node.v for node in self.tree[begin:end])
def query_all_max(self,):
"""
查找x,y区间的最大值
"""
begin = self.split(0)
end = self.split(10**9+1)
return max(node.v for node in self.tree[begin:end])
def query_all_intervals(self):
tree = self.tree
lines = []
l = r = -1
for node in tree :
if node.v == 0:
if l != -1:
lines.append([l,r])
l = -1
else:
if l == -1:
l = node.l
r = node.r
return lines
class SummaryRanges:
def __init__(self):
self.odt = ODT(0,10**4+1,0)
def addNum(self, val: int) -> None:
self.odt.assign(val,val,1)
def getIntervals(self) -> List[List[int]]:
return self.odt.query_all_intervals()
210

被折叠的 条评论
为什么被折叠?



