【周赛总结】第193场周赛——制作花(合并选取区间),树节点的第 K 个祖先

2020/06/14 rank 1173/3803 ac 2

引言

状态不是很好,这周只a了两道题,思路不畅。

制作m束花的天数

在这里插入图片描述

首先想到采用二分的方法,核心在于注意到题目的解具有单调性,也就是说,在第i天可以,则在之后的第i+1天也是都可以的。

class Solution:
    def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
        ## 二分的方法
        right = max(bloomDay)
        left = 1

        def valid(mid):
            flower = 0
            need = m
            for i in range(len(bloomDay)):
                if bloomDay[i]<=mid:
                    flower += 1
                else:
                    need -= flower//k
                    flower = 0
            need -= flower//k
            return need<=0

        while left<=right:
            mid = left+(right-left)//2
            if valid(mid):
                right = mid-1
            else:
                left = mid+1
        if left>max(bloomDay):
            return -1
        return left

另外一个方法是我在答题时候的思路,但是考场上没有能做出来。也就是利用字典,维护区间的算法。其实很类似于并查集。利用两个字典维护每一个连续数组的左右边界。

需要注意,字典r是维护了一个右侧连续数组的右端点,l维护了一个左侧连续数组的左端点。

class Solution(object):
    def minDays(self, bloomDay, m, k):
        """
        :type bloomDay: List[int]
        :type m: int
        :type k: int
        :rtype: int
        """
        ## 区间合并的算法
        days = []
        for i in range(len(bloomDay)):
            days.append([bloomDay[i], i])
        days.sort(key = lambda x:x[0])
        r = {}
        l = {}
        sum_ = 0

        def get(left, right):
            return (right-left+1)//k

        for day,index in days:
            if index-1 in l and index+1 in r:
                sum_ = sum_ - get(l[index-1],index-1) - get(index+1,r[index+1]) + get(l[index-1],r[index+1]) 
                ## 这一步的更新需要注意,更改最左边位置的右界限和最右边位置的左边界。
                r[l[index-1]] = r[index+1]
                l[r[index+1]] = l[index-1]
            elif index-1 in l:
                sum_ = sum_ - get(l[index-1],index-1) + get(l[index-1],index)
                r[l[index-1]] = index
                l[index] = l[index-1]
            elif index+1 in r:
                sum_ = sum_- get(index+1,r[index+1]) + get(index,r[index+1])
                l[r[index+1]] = index
                r[index] = r[index+1]
            else:
                r[index] = index
                l[index] = index
                sum_ += get(index,index)
            print(sum_)
            if sum_ >=m:
                return day
        return -1

树上倍增

在这里插入图片描述在这里插入图片描述

树上倍增算法

class TreeAncestor:

    def __init__(self, n: int, parent: List[int]):
        self.cols = 20      # log(50000) < 20

        self.dp = [[-1] * self.cols for _ in range(n)]
        for i in range(n):
            self.dp[i][0] = parent[i]

        # 动态规划设置祖先, dp[node][j] 表示 node 往前推第 2^j 个祖先
        for j in range(1, self.cols):
            for i in range(n):
                if self.dp[i][j-1] != -1:
                    self.dp[i][j] = self.dp[self.dp[i][j-1]][j-1]
        return

    def getKthAncestor(self, node: int, k: int) -> int:
        for i in range(self.cols - 1, -1, -1):
            if k & (1 << i):
                node = self.dp[node][i]
                if node == -1:
                    break
        return node


# Your TreeAncestor object will be instantiated and called as such:
# obj = TreeAncestor(n, parent)
# param_1 = obj.getKthAncestor(node,k)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值