周赛399(240526)
这场掉分了,第四题没思路,而且罚时太多了😥
第三题3164. 优质数对的总数 II
题目大意:
给定两个整数数组nums1和nums2,以及一个正整数k。如果nums1[i]可以被nums2[j]*k整除,则称数对(i, j)为优质数对。要求计算优质数对的总数。
实现思路:
- 首先,使用
Counter统计nums1中可以被k整除的数除以k的结果,得到c1。 - 然后,找到
c1中的最大值mx,如果c1为空,则mx为0。 - 使用
Counter统计nums2中各个数出现的次数,得到c2。 - 初始化结果
res为0。 - 遍历
c2中的每个数nm和其出现的次数c,对于每个数nm,从nm开始递增到mx,步长为nm,计算c * c1[j]并累加到res中。 - 最终返回
res作为优质数对的总数。
class Solution:
def numberOfPairs(self, nums1: List[int], nums2: List[int], k: int) -> int:
c1 = Counter(nm//k for nm in nums1 if nm%k==0)
mx = max(nm for nm, _ in c1.items()) if c1 else 0
c2 = Counter(nums2)
res = 0
for nm, c in c2.items():
for j in range(nm, mx+1, nm):
res += c * c1[j]
return res
第四题3165. 不包含相邻元素的子序列的最大和
题目大意
给定一个整数数组 nums 和一个二维数组 queries,其中 queries[i] = [posi, xi] 表示对于每个查询 i,首先将 nums[posi] 设置为 xi,然后计算查询 i 的答案。答案为 nums 中不包含相邻元素的子序列的最大和。最终返回所有查询的答案之和。
实现思路
- 构建线段树:使用线段树维护区间的最大和。
- 线段树节点
tr[u]存储了四个值,分别表示:- 不跨越区间的最大和(无相邻元素)。
- 区间左端点为起点的最大和(无相邻元素)。
- 区间右端点为起点的最大和(无相邻元素)。
- 区间的最大和。
- 定义
pushup函数更新节点值,定义build函数构建线段树。
- 线段树节点
- 更新操作:更新线段树中的节点值。
- 定义
update函数更新线段树中的节点值。
- 定义
- 遍历查询:对每个查询,更新
nums中对应位置的值,并计算当前的最大和。 - 最终返回所有查询的答案之和,记得对结果取模。
class Solution:
def maximumSumSubsequence(self, nums: List[int], queries: List[List[int]]) -> int:
def pushup(u):
l, r = tr[u<<1], tr[u<<1|1]
tr[u][0] = max(l[1]+r[0], l[0]+r[2])
tr[u][1] = max(l[0]+r[3], l[1]+r[1])
tr[u][2] = max(l[2]+r[2], l[3]+r[0])
tr[u][3] = max(l[2]+r[3], l[3]+r[1])
def build(u, l, r):
if l==r:
tr[u][3] = max(nums[l], 0)
else:
mid = l+r>>1
build(u<<1, l, mid)
build(u<<1|1, mid+1, r)
pushup(u)
def update(u, l, r, x, val):
if l==r:
tr[u][3] = max(0, val)
return
mid = l+r>>1
if x<=mid:
update(u<<1, l, mid, x, val)
else:
update(u<<1|1, mid+1, r, x, val)
pushup(u)
n = len(nums)
tr = [[0]*4 for _ in range(1<<n.bit_length() + 1)]
mod = int(1e9) + 7
res = 0
build(1, 0, n-1)
for pos, x in queries:
update(1, 0, n-1, pos, x)
res = (res + tr[1][3])%mod
return res