一、本周周赛总结
- 感觉有奖品大家都来了。
- T1 数学。
- T2 dp。
- T3 dp。
- T4 差分/BIT RUPQ。
6451. 找出最大的可达成数字
6451. 找出最大的可达成数字
1. 题目描述
2. 思路分析
- 为了使x num在t步内相同,需要相向而行,每步最大缩短距离是2,那么t步距离是2t。
3. 代码实现
class Solution:
def theMaximumAchievableX(self, num: int, t: int) -> int:
return num+2*t
6899. 达到末尾下标所需的最大跳跃次数
6899. 达到末尾下标所需的最大跳跃次数
1. 题目描述
2. 思路分析
- 每个位置都尝试向后跳即可。
- 思考,如果n<=1e5咋做?
- 改成填表法,然后用离散化线段树维护前边的max。
- 要离散的数据是nums里所有v v-t v+t。
- 这题由于n小,所以用BIT甚至更快。
3. 代码实现
class Solution:
def maximumJumps(self, nums: List[int], t: int) -> int:
n = len(nums)
f = [-inf]*n
f[0] = 0
for i in range(n-1):
for j in range(i+1,n):
if abs(nums[j]-nums[i]) <= t:
f[j] = max(f[j],f[i]+1)
return f[-1] if f[-1] > -inf else -1
nlgn线段树做法
class ZKW:
# n = 1
# size = 1
# log = 2
# d = [0]
# op = None
# e = 10 ** 15
"""自低向上非递归写法线段树,0_indexed
tmx = ZKW(pre, max, -2 ** 61)
"""
__slots__ = ('n', 'op', 'e', 'log', 'size', 'd')
def __init__(self, V, OP, E):
"""
V: 原数组
OP: 操作:max,min,sum
E: 每个元素默认值
"""
self.n = len(V)
self.op = OP
self.e = E
self.log = (self.n - 1).bit_length()
self.size = 1 << self.log
self.d = [E for i in range(2 * self.size)]
for i in range(self.n):
self.d[self.size + i] = V[i]
for i in range(self.size - 1, 0, -1):
self.update(i)
def set(self, p, x):
# assert 0 <= p and p < self.n
update = self.update
p += self.size
self.d[p] = x
for i in range(1, self.log + 1):
update(p >> i)
def get(self, p):
# assert 0 <= p and p < self.n
return self.d[p + self.size]
def query(self, l, r): # [l,r)左闭右开
# assert 0 <= l and l <= r and r <= self.n
sml, smr, op, d = self.e, self.e, self.op, self.d
l += self.size
r += self.size
while l < r:
if l & 1:
sml = op(sml, d[l])
l += 1
if r & 1:
smr = op(d[r - 1], smr)
r -= 1
l >>= 1
r >>= 1
return self.op(sml, smr)
def all_query(self):
return self.d[1]
def max_right(self, l, f):
"""返回l右侧第一个不满足f的位置"""
# assert 0 <= l and l <= self.n
# assert f(self.e)
if l == self.n:
return self.n
l += self.size
sm, op, d, size = self.e, self.op, self.d, self.size
while True:
while l % 2 == 0:
l >>= 1
if not (f(op(sm, d[l]))):
while l < size:
l = 2 * l
if f(op(sm, d[l])):
sm = op(sm, d[l])
l += 1
return l - size
sm = op(sm, d[l])
l += 1
if (l & -l) == l:
break
return self.n
def min_left(self, r, f):
"""返回r左侧连续满足f的最远位置的位置"""
# assert 0 <= r and r < self.n
# assert f(self.e)
if r == 0:
return 0
r += self.size
sm, op, d, size = self.e, self.op, self.d, self.size
while True:
r -= 1
while r > 1 and (r % 2):
r >>= 1
if not (f(op(d[r], sm))):
while r < size:
r = (2 * r + 1)
if f(op(d[r], sm)):
sm = op(d[r], sm)
r -= 1
return r + 1 - size
sm = op(d[r], sm)
if (r & -r) == r:
break
return 0
def update(self, k):
self.d[k] = self.op(self.d[2 * k], self.d[2 * k + 1])
def __str__(self):
return str([self.get(i) for i in range(self.n)])
class Solution:
def maximumJumps(self, nums: List[int], t: int) -> int:
n = len(nums)
h = set(nums)
for v in nums:
h.add(v-t)
h.add(v+t)
h = sorted(h)
size = len(h)
f = ZKW([-inf]*size,max,-inf)
f.set(bisect_left(h,nums[0]),0)
for i in range(1,n):
l,r = bisect_left(h,nums[i]-t),bisect_right(h,nums[i]+t)
i = bisect_left(h,nums[i])
ans = max(f.get(i), f.query(l,r)+1)
f.set(i,ans)
return [-1,ans][ans>-inf]
6912. 构造最长非递减子数组
6912. 构造最长非递减子数组
1. 题目描述
2. 思路分析
- dp。
- 定义f[i][0/1]为以i为右端点时,分别使用num1 num2中数字时的最长长度。
- 那么转移分别讨论前一个数大小即可。
- 实现时可以省去第一维度。
3. 代码实现
class Solution:
def maxNonDecreasingLength(self, nums1, nums2):
n = len(nums1)
x = y = 1
ans = 1
for i in range(1,n):
a=b=1
if nums1[i] >= nums1[i-1]:
a = x+1
if nums1[i] >= nums2[i-1]:
a = max(a,y+1)
if nums2[i] >= nums1[i-1]:
b = x+1
if nums2[i] >= nums2[i-1]:
b = max(b,y+1)
ans = max(ans,a,b)
x,y = a,b
return ans
6919. 使数组中的所有元素都等于零
6919. 使数组中的所有元素都等于零
1. 题目描述
2. 思路分析
- 一眼RUPQ,且是顺序的,所以强行写差分wa半天。
- 早知道直接BIT了。
3. 代码实现
差分
文章来源:https://www.toymoban.com/news/detail-551667.html
class Solution:
def checkArray(self, nums: List[int], k: int) -> bool:
n = len(nums)
d = [0]*(n+1)
d[0] = nums[0]
for i in range(1,n):
d[i] = nums[i] - nums[i-1]
for i in range(n-k+1):
# print(i)
if d[i]<0:
# print(i,d[i])
return False
d[i+k] += d[i]
d[i]-=d[i]
# print(d)
if all(v==0 for v in d[:-1]) :
return True
return False
BIT
文章来源地址https://www.toymoban.com/news/detail-551667.html
class BinIndexTreeRUPQ:
"""树状数组的RUPQ模型,结合差分理解"""
def __init__(self, size_or_nums): # 树状数组,下标需要从1开始
# 如果size 是数字,那就设置size和空数据;如果size是数组,那就是a
if isinstance(size_or_nums, int):
self.size = size_or_nums
self.c = [0 for _ in range(self.size + 5)]
else:
self.size = len(size_or_nums)
self.c = [0 for _ in range(self.size + 5)]
for i, v in enumerate(size_or_nums):
self.add_interval(i + 1, i + 1, v)
def add_point(self, i, v): # 单点增加,下标从1开始;不支持直接调用,这里增加的是差分数组的单点
while i <= self.size:
self.c[i] += v
i += i&-i
def sum_prefix(self, i): # 前缀求和,下标从1开始;不支持直接调用,这里求和的是差分数组的前缀和
s = 0
while i >= 1:
s += self.c[i]
i &= i-1
return s
def add_interval(self, l, r, v): # 区间加,下标从1开始,把[l,r]闭区间都加v
self.add_point(l, v)
self.add_point(r + 1, -v)
def query_point(self, i): # 单点询问值,下标从1开始,返回i位置的值
return self.sum_prefix(i)
def lowbit(self, x):
return x & -x
class Solution:
def checkArray(self, nums: List[int], k: int) -> bool:
n = len(nums)
bit = BinIndexTreeRUPQ(nums)
for i in range(n-k+1):
p = bit.query_point(i+1)
if p < 0:
return False
bit.add_interval(i+1,i+k,-p)
if all(bit.query_point(i)==0 for i in range(1,n+1)) :
return True
return False
参考链接
到了这里,关于[LeetCode周赛复盘] 第 353 场周赛20230709的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!