[LeetCode周赛复盘] 第 349 场周赛20230611

本周LeetCode周赛涵盖了四种类型的题目,包括寻找既不是最小值也不是最大值的数、字典序最小字符串操作、收集巧克力的最小成本以及最大和查询问题。解题策略涉及遍历、贪心模拟、贪心枚举以及离线+线段树的方法。代码实现中展示了如何运用这些策略解决具体问题。
摘要由CSDN通过智能技术生成

一、本周周赛总结

  • T1 遍历。
  • T2 贪心模拟。
  • T3 贪心枚举。
  • T4 贪心离线+线段树。
    在这里插入图片描述

6470. 既不是最小值也不是最大值

6470. 既不是最小值也不是最大值

1. 题目描述

在这里插入图片描述

2. 思路分析

按题意模拟即可。

3. 代码实现

class Solution:
    def findNonMinOrMax(self, nums: List[int]) -> int:
        mn,mx = min(nums),max(nums)
        for v in nums:
            if mn != v != mx:
                return v
        return -1

6465. 执行子串操作后的字典序最小字符串

6465. 执行子串操作后的字典序最小字符串

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 贪心。
  • 如果前边是a就跳过,然后找到第一个不是a的位置开始操作,直到遇到a。
  • 由于题目要求最少一次,特判全a的数据,把最后一个字符变z。

3. 代码实现

class Solution:
    def smallestString(self, s: str) -> str:
        n = len(s)
        i = 0 
        while i<n and s[i] =='a':
            i += 1
        l = s[:i]
        r = list(s[i:])
        if not r:
            return l[:-1]+'z'
        for i,v in enumerate(r):
            if v == 'a':break 
            r[i] = chr(ord(v)-1)
        return l+''.join(r)

6449. 收集巧克力

6449. 收集巧克力

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 枚举操作次数,每个位置计算可能的最小值即可。

3. 代码实现

class Solution:
    def minCost(self, nums: List[int], x: int) -> int:
        n = len(nums)
        mn = nums[:]
        ans = sum(nums)
        for i in range(1, n):
            nums = nums[-1:] + nums[:-1]
            for j in range(n):
                mn[j] = min(mn[j], nums[j])
            ans = min(ans, i * x + sum(mn))
        return ans

6473. 最大和查询

6473. 最大和查询

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 一眼出思路离线,由于限制是要最大的,因此降序处理。
  • 对于每个query里的x,把所有num1>=x的组合记录,记的数据是(num1,num1+num2)。
  • 然后对query里的y找集合里所有超过y的数据对应的最大值,那么可以用线段树处理区间最大值。

  • 由于y的数据范围很大,需要离散化,数据是query的y和nums2。
  • 或者直接用动态开点也可以。
    在这里插入图片描述

3. 代码实现

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 maximumSumQueries(self, nums1: List[int], nums2: List[int], queries: List[List[int]]) -> List[int]:
        n = len(nums1)
        hs = sorted(set(nums2+[y for _,y in queries]))
        size = len(hs)
        a = sorted(zip(nums1,nums2),reverse=True)
        # print(a)
        j = 0
        ans = [-1]*len(queries)
        tree = ZKW([-inf]*size,max,-inf)
        size = max(max(nums2),max(y for _,y in queries))+1
        # print(size)
        for x,y,i in sorted([(x,y,i) for i,(x,y) in enumerate(queries)],reverse=True):
            while j < n and a[j][0] >= x:       
                p = bisect_left(hs,a[j][1])
                tree.set(p,max(a[j][1]+a[j][0],tree.query(p,p+1)))              
                j += 1
            mx = tree.query(bisect_left(hs,y),bisect_left(hs,size+1))
            # print(i,x,y,mx)
            ans[i] = mx if mx > -inf else -1
        return ans                             

参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值