周赛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