第 338 场周赛
Q1
前k个最大的数。
class Solution:
def kItemsWithMaximumSum(self, numOnes: int, numZeros: int, numNegOnes: int, k: int) -> int:
a=[1]*numOnes+[0]*numZeros+[-1]*numNegOnes
a.sort()
ans=0
for i in range(k):
ans+=a[-i-1]
return ans
Q2
暴力找。
class Solution:
def primeSubOperation(self, nums: List[int]) -> bool:
primes = []
for i in range(2, 1001):
flag = True
for j in range(2, int(i**0.5)+1):
if i % j == 0:
flag = False
break
if flag:
primes.append(i)
primes.sort()
n, pre = len(nums), float('-inf')
for i in range(n):
# 二分查找第一个比nums[i]小的质数的位置
l, r, pos = 0, len(primes)-1, -1
while l <= r:
mid = (l + r) // 2
if primes[mid] < nums[i]:
pos = mid
l = mid + 1
else:
r = mid - 1
for j in range(pos, -1, -1):
if nums[i] - primes[j] > pre:
nums[i] -= primes[j]
break
if nums[i] <= pre:
return False
pre = nums[i]
return True
Q3
观察到如果要操作为的数是 x ,x大于区间所有的数 , 假设区间和为sum , 则答案是 x*n-sum。
x小于区间所有的数,答案是 sum-n*x。所以考虑一般情况,如果在(min,max)之间的数,可以用x将整个数组分成两部分计算,可以使用排序后二分查找第一个大于等于x的数。分两种情况计算,
class Solution:
def minOperations(self, nums: List[int], queries: List[int]) -> List[int]:
nums.sort()
sum = [nums[0]]
for i in range(1, len(nums)):
sum.append(nums[i] + sum[i - 1])
n = len(nums)
ans = []
for x in queries:
l, r, pos = 0, n - 1, -1
while l <= r:
mid = (l + r) // 2
if nums[mid] >= x:
pos = mid
r = mid - 1
else:
l = mid + 1
if nums[0] >= x:
ans.append(sum[n - 1] - n * x)
elif nums[-1] < x:
ans.append(n * x - sum[-1])
else:
if nums[pos] == x:
ans.append((pos + 1) * x - sum[pos] + sum[n - 1] - sum[pos] - x * (n - pos - 1))
else:
pos -= 1
ans.append((pos + 1) * x - sum[pos] + sum[n - 1] - sum[pos] - x * (n - pos - 1))
return ans
Q4
不会啊。感觉是树形DP,但是DP不出来。