Koko loves to eat bananas.  There are N piles of bananas, the i-th pile has piles[i] bananas.  The guards have gone and will come back in H hours.
Koko can decide her bananas-per-hour eating speed of K.  Each hour, she chooses some pile of bananas, and eats K bananas from that pile.  If the pile has less than K bananas, she eats all of them instead, and won't eat any more bananas during this hour.
Koko likes to eat slowly, but still wants to finish eating all the bananas before the guards come back.
Return the minimum integer K such that she can eat all the bananas within H hours.
 
Example 1:
Input: piles = [3,6,7,11], H = 8
Output: 4
Example 2:
Input: piles = [30,11,23,4,20], H = 5
Output: 30
Example 3:
Input: piles = [30,11,23,4,20], H = 6
Output: 23

 
Constraints:

1 <= piles.length <= 10^4
piles.length <= H <= 10^9
1 <= piles[i] <= 10^9

Difficulty: interview

Starter code:

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        

Solutions:
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        bananas = sum(piles)
        K = bananas // H + (bananas % H != 0)
        while True:
            hours_needed = 0
            for pile in piles:
                hours_needed += pile // K
                if pile % K != 0:
                    hours_needed += 1
            if hours_needed <= H:
                return K
            K += 1


import math

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        total_bananas = sum(piles)
        left, right = math.ceil(total_bananas / H), math.ceil(total_bananas / (H - len(piles) + 1))
        while left < right:
            mid = (left + right) // 2
            if not sum([math.ceil(pile/mid) for pile in piles]) <= H:
                left = mid + 1
            else:
                right = mid
        return left

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def time_need(K):
            return sum(p//K + (1 if p%K else 0) for p in piles)
        
        low = max(1, sum(piles)//H)
        high = max(piles)
        while low < high:
            if time_need(low)<=H: return low
            
            low += 1
            mid = (low+high)//2
            if time_need(mid) > H:
                low = mid + 1
            else:
                high = mid
        
        return low

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def helper(k):
            ret=0
            for pile in piles:
                ret+=math.ceil(pile/k)
                if ret>H:
                    return False
            return True
        l,r=1,max(piles)
        while l<=r:
            mid=l+(r-l)//2
            if helper(mid):
                r=mid-1
            else:
                l=mid+1
        return l


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # if len(piles) == 1:return -(piles[0] // -H)
        self.piles = piles
        l, r = 1, max(piles)
        
        while l <= r:
            K = (l + r)//2
            if self.eat_time(K) <= H:
                r = K - 1
            else:
                l = K + 1
        return l
            
    def eat_time(self, K):
        cnt = 0
        for banana in self.piles:
            q, mod = divmod(banana, K)
            cnt += q
            if mod != 0: cnt += 1
            # cnt += banana / K
            # if banana%K != 0: cnt += 1
        return cnt

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def enough(n):
            hrs = 0
            for i in piles:
                if n > i:
                    hrs += 1
                elif i % n == 0:
                    hrs += i // n
                else:
                    hrs += (i // n) + 1
            return hrs <= H
        
        l,r = 1,sum(piles)
        while l < r:
            m = (l + r) // 2
            if not enough(m):
                l = m + 1
            else:
                r = m
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        left, right = 1, max(piles)
        while left <= right:
            mid = left + (right - left) // 2
            if self.condition(piles, H, mid):
                right = mid - 1
            else:
                left = mid + 1
        return left
    
    def condition(self, piles, H, k):
        hours = 0
        for pile in piles:
            div, rem = divmod(pile, k)
            hours += div
            if rem != 0:
                hours += 1
        return hours <= H

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def can(K):
            cur = H
            for a in piles:
                cur -= a//K
                cur -= (a%K!=0)
            return cur >= 0
        l, r = 1, sum([a+ 1 for a in piles])
        while l<r:
            mid = (l + r)//2
            if can(mid):
                r = mid
            else:
                l = mid + 1
        return l

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        end = max(piles)
        start = 1
        while start + 1 < end:
            mid = start + (end - start) // 2 
            if self.possible(mid, piles, H):
                end = mid 
            else:
                start = mid 
        
        if self.possible(start,piles,H):
            return start 
        if self.possible(end, piles, H):
            return end 
        
    
    def possible(self, eat_load, total_load, hour):
        return sum([math.ceil(-k / -eat_load) for k in total_load]) <= hour 

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # Minimum value we can have is the sum of piles / H
        lo = sum(piles) // H
        
        # Maximum would be the maximum value in the list
        hi = max(piles)
        
        #
        #         lo = 0
        #         hi = float('-inf')

        #         for pile in piles:
        #             lo += pile
        #             hi = max(hi, pile)

        #         lo =// H
        
        if len(piles) == 1:
            return ceil(piles[0] / H)
        
        while lo <= hi:
            mid = (lo + hi) // 2
            
            count = sum(map(lambda x: ceil(x / mid), piles))
            
            if count > H:
                lo = mid + 1
            else:
                hi = mid - 1
        
        return lo

class Solution:
    
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def useDays(pile, speed):
            days = pile // speed
            return days if pile % speed == 0 else days + 1
        
        def CanDone(piles, speed, H):
            numDays = 0
            for num in piles:
                numDays += useDays(num, speed)
            return numDays <= H
        
        maxEat = max(piles)
        left,right = 1, maxEat + 1
        while left < right:
            mid = left + ((right-left)>>1)            
            if CanDone(piles, mid, H):
                right = mid
            else:
                left = mid + 1
        return left
            


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        #piles.sort()
        
        lo, hi = 1, max(piles)
        ans = hi
        while lo <= hi:
            k = (lo + hi) // 2
            time = 0
            for i in piles:
                t = int(ceil(i / k))
                if not t:
                    t += 1
                time += t
                
            #print(k, time)
            if time <= H:
                hi = k - 1
                ans = k
            else:
                lo = k + 1
        
        return ans

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        piles.sort()
        
        lo, hi = 1, piles[-1]
        ans = hi
        while lo <= hi:
            k = (lo + hi) // 2
            time = 0
            for i in piles:
                t = int(ceil(i / k))
                if not t:
                    t += 1
                time += t
                
            #print(k, time)
            if time <= H:
                hi = k - 1
                ans = k
            else:
                lo = k + 1
        
        return ans

import math as m
class Solution:
    def check_time(piles,speed):
        hrs=0
        for i in piles:
            hrs+=int(m.ceil(i/speed))
        return hrs
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        low=1
        high=float('-inf')
        for i in piles:
            high=max(high,i)
        if H==len(piles):
            return high
        while(low<=high):
            mid=(low+high)//2
            hrs=Solution.check_time(piles,mid)
            if hrs>H:
                low=mid+1
            else:
                high=mid-1
        return low


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # want to search for K - this is the variable to change
        
        # if piles in sorted order - based on length of pile and hours - need to get average eats in the pile
        
        # let K = 1 to max(piles)
        
        # per hour - go through the piles and eat K bananas before time limit is up
        # O(N) time to go through all piles N
        # K is split via binary search log(K)
        
        # log(K) * N times
        
        low = 1
        high = max(piles)
        
        # the piles is not the one we want to find - its K
        
        # take too much time to eat - raise K
        # too little time to eat - lower K
        # set timer
        # always a solution
        def possible(k):
            time = 0
            # find out how much time it takes
            for pile in piles:
                time += (pile - 1) // k + 1
            return time <= H
        
        while low <= high:
            mid = low + (high - low) // 2
            outcome = possible(mid)
            
            # check if its possible
            if possible(mid): # just right
                high = mid - 1
            else:
                low = mid + 1

        return low # should not hit - always solution

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if len(piles)==H:
            return max(piles)
        low=1
        high=max(piles)
        ans=high
        while low<=high:
            mid=(low+high)//2
            h=H
            for i in range(len(piles)):
                if piles[i]<=mid:
                    h-=1
                else:
                    if piles[i]%mid==0:
                        h-=piles[i]//mid
                    else:
                        h-=(piles[i]//mid)+1
            if h>=0:
                ans =min(ans,mid)
                high=mid-1
            else:
                low=mid+1
        return ans

from math import ceil
class Solution:
    def ok(self, piles: List[int], k: int, H: int) -> bool:
        return sum([ ceil(piles[i] / k) for i in range(len(piles)) ]) <= H
    
    
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        st = 1
        en = sum(piles)
        
        ans = en
        
        while st <= en:
            mid = st + (en - st) // 2
            
            if self.ok(piles, mid, H):
                ans = mid
                en = mid - 1
                
            else:
                st = mid + 1
                
        return ans

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        L = len(piles)
        if L==H:
            return max(piles)
        k2 = max(piles)
        k1 = 1
        res = k2
        k = k1
        while k1<k2-1:
            
            cur = 0
            for j in range(L):
                cur += math.ceil(piles[j]/k)
                if cur>H:
                    k1 = k
                    break
            if cur<=H:
                k2 = k
                res = min(res,k)
            #print(k1,k2,k,cur)
            k = (k1+k2)//2
        return res


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def time(val):
            t = len(piles)
            for pile in piles:
                t += (pile - 1) // val
            return t
            
        l, r = 1, max(piles)
        while l <= r:
            mid = l + (r - l) // 2
            t = time(mid)
            if t <= H:
                r = mid - 1
            else:
                l = mid + 1
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # want to search for K - this is the variable to change
        
        # if piles in sorted order - based on length of pile and hours - need to get average eats in the pile
        
        # let K = 1 to max(piles)
        
        # per hour - go through the piles and eat K bananas before time limit is up
        # O(N) time to go through all piles N
        # K is split via binary search log(K)
        
        # log(K) * N times
        
        low = 1
        high = max(piles)
        
        # the piles is not the one we want to find - its K
        
        # take too much time to eat - raise K
        # too little time to eat - lower K
        # set timer
        # always a solution
        def possible(k):
            time = 0
            # find out how much time it takes
            for pile in piles:
                time += (pile + k - 1) // k # if k >= pile then it will be 1.xxxxx that means we ate the pile
                # if there is 0, then that means 
            return time <= H
        
        while low < high:
            mid = low + (high - low) // 2
            outcome = possible(mid)
            
            # check if its possible
            if possible(mid): # reduce because anything greater will be satisfied - need to find left bound
                high = mid
            else: # not possible - need to increase K to eat faster
                low = mid + 1

                # low == high
        return high # should not hit - always solution

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # want to search for K - this is the variable to change
        
        # if piles in sorted order - based on length of pile and hours - need to get average eats in the pile
        
        # let K = 1 to max(piles)
        
        # per hour - go through the piles and eat K bananas before time limit is up
        # O(N) time to go through all piles N
        # K is split via binary search log(K)
        
        # log(K) * N times
        
        low = 1
        high = max(piles)
        
        # the piles is not the one we want to find - its K
        
        # take too much time to eat - raise K
        # too little time to eat - lower K
        # set timer
        # always a solution
        def possible(k):
            time = 0
            # find out how much time it takes
            for pile in piles:
                time += (pile + k - 1) // k # if k >= pile then it will be 1.xxxxx that means we ate the pile
                # if there is 0, then that means 
            return time <= H
        
        while low < high:
            mid = low + (high - low) // 2
            outcome = possible(mid)
            
            # check if its possible
            if possible(mid): # reduce because anything greater will be satisfied - need to find left bound
                high = mid
            else: # not possible - need to increase K to eat faster
                low = mid + 1

        return low # should not hit - always solution

class Solution:
    def minEatingSpeed(self, array: List[int], hour: int) -> int:
        if len(array)==hour:
            return max(array)
        low=1
        high=max(array)
        ans=high
        while low<=high:
            mid=(low+high)//2
            h=hour
            for i in range(len(array)):
                if array[i]<=mid:
                    h-=1
                else:
                    if array[i]%mid==0:
                        h-=array[i]//mid
                    else:
                        h-=(array[i]//mid)+1
            if h>=0:
                ans =min(ans,mid)
                high=mid-1
            else:
                low=mid+1
        return ans



class Solution:
    def minEatingSpeed(self, piles, H):
        speed = math.floor(sum(piles) / H)
        while True:
            time = sum([math.ceil(x / speed) if speed else float('inf') for x in piles])
            print(f'{speed=}, {time=}, {H=}')
            if time <= H: break
            speed += 1
        return speed



import math

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        self.store = {}

        l = 1
        r = max(piles)
        while l <= r:
            m = l + (r-l)//2
            if self.calc_h(piles, m) > H:
                l = m + 1
            else:  # calc_h(piles, m) <= H
                if m == 1 or self.calc_h(piles, m-1) > H:
                    return m
                r = m - 1

    def calc_h(self, piles, K):
        if K not in self.store:
            h = [p // K + (p%K > 0) for p in piles]
            self.store[K] = int(sum(h))
        return self.store[K]


import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        l = 1
        r = max(piles)
        while l <= r:
            m = l + (r-l)//2
            if calc_h(piles, m) > H:
                l = m + 1
            else:  # calc_h(piles, m) <= H
                if m == 1 or calc_h(piles, m-1) > H:
                    return m
                r = m - 1

def calc_h(piles, K):
    h = [p // K + (p%K > 0) for p in piles]
    return int(sum(h))


import math

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        total_bananas = sum(piles)
        left, right = math.ceil(total_bananas / H), total_bananas
        print(left, right)
        while left < right:
            mid = (left + right) // 2
            if not sum([math.ceil(pile/mid) for pile in piles]) <= H:
                left = mid + 1
            else:
                right = mid
        return left

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def condition(k) -> bool:
            count = 0
            
            for v in piles:
                count += int(math.ceil(v / k))
                if count > H:
                    return False
            return True
        
        left,right = 1,max(piles)
        while left < right:
            mid = left + (right - left) // 2
            if condition(mid):
                right = mid
            else:
                left = mid + 1
            
        return left

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if not piles: return -1
        
        low,high=1,sum(piles)
        
        def isPossible(piles,target,H):
            
            return sum(math.ceil(p/target) for p in piles) <= H
       
        while low < high:
            
            mid = low+(high-low)//2
            # print(low,high,mid)
            if isPossible(piles,mid,H):
                high = mid
            else:
                low = mid+1
                
        return low
        


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        left = 1
        right = max(piles)
        while left < right:
            mid = (left + right) // 2
            if self.get_total_days(piles, mid) > H:
                left = mid + 1
            else:
                right = mid
        return left
    
    def get_total_days(self, piles: List[int], num_eat: int)-> int:
        if num_eat == 0:
            return 0
        total_days = 0
        for pile in piles:
            total_days += math.ceil(float(pile) / num_eat)
        return total_days

class Solution:
    def minEatingSpeed(self, array: List[int], hour: int) -> int:
        if len(array)==hour:
            return max(array)
        low=1
        high=max(array)
        ans=high
        while low<=high:
            mid=(low+high)//2
            h=hour
            for i in range(len(array)):
                if array[i]<=mid:
                    h-=1
                else:
                    if array[i]%mid==0:
                        h-=array[i]//mid
                    else:
                        h-=(array[i]//mid)+1
                if h<0:
                    break 
            if h>=0:
                ans =mid
                high=mid-1
            else:
                low=mid+1
        return ans


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def possible(K):
            return sum((p-1) //K+ 1 for p in piles) <= H

        lo, hi = 1, max(piles)
        while lo < hi:
            mi = (lo + hi) //2
            if not possible(mi):
                lo = mi + 1
            else:
                hi = mi
        return lo

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
 
        maxB = max(piles)

        def getH(k):
            if not k:
                return float('inf')
            numHours = 0
            for pile in piles:
                numHours += pile//k + int(bool(pile%k))
            return numHours

        
        
        def bs(start, end):
            if start > end:
                return float('inf')
            mid = (start + end + 1)//2
            h = getH(mid)
            # print(mid, h)
            if h < H:
                if mid != start :
                    return min(mid,bs(start, mid-1))
            if h > H:
                return bs(mid+1, end)
            if h == H:
                while getH(mid-1) == H:
                    mid -= 1
            return mid
        
        return  bs(0, maxB)


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def time_needed(K):
            return sum(p//K + (1 if p%K else 0) for p in piles)
        
        lower = max(1, sum(piles)//H)
        upper = max(piles)
        
        while lower < upper:
            if time_needed(lower) <= H:
                return lower
            
            lower += 1
            mid = (lower + upper)//2
            if time_needed(mid) <= H:
                upper = mid
            else:
                lower = mid + 1
                
        return lower

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        #piles.sort()
        
        lo, hi = 1, max(piles)
        ans = hi
        while lo <= hi:
            k = (lo + hi) // 2
            time = 0
            for i in piles:
                t = int(ceil(i / k))
                if not t:
                    t += 1
                time += t
                
                if time > H:
                    break
                
            #print(k, time)
            if time <= H:
                hi = k - 1
                ans = k
            else:
                lo = k + 1
        
        return ans

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
 
        maxB = max(piles)

        def getH(k):
            if not k:
                return float('inf')
            numHours = 0
            for pile in piles:
                numHours += pile//k + int(bool(pile%k))
            return numHours

        
        
        def bs(start, end):
            if start > end:
                return float('inf')
            mid = (start + end + 1)//2
            h = getH(mid)
            # print(mid, h)
            if h < H:
                if mid > start :
                    return min(mid,bs(start, mid-1))
            if h > H:
                return bs(mid+1, end)
            if h == H:
                while getH(mid-1) == H:
                    mid -= 1
            return mid
        
        return  bs(0, maxB)


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        max_k = 0
        for value in piles:
            max_k = max(max_k, value)
        
        def possible(k):
            hours = 0
            for item in piles:
                hours += math.ceil(item / k)
                if hours > H:
                    return False
            if hours <= H:
                return True
            return False
        
        def binary_search(low, high):
            mid = low + (high - low)//2
            if possible(low):
                return low
            elif possible(mid):
                return binary_search(low, mid)
            else:
                return binary_search(mid+1, high)
        
        def binary_search_iter(low, high):
            pass
        
        return binary_search(1, max_k)

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # Find the first <= in  [> > > > > <= <=]
        n = len(piles)
        low, high = 1, max(piles)
        while (low + 1) < high:
            mid = low + ((high - low) // 2)
            used_hrs = self.calc_hours(piles, mid)
            #print(mid, used_hrs)
            if used_hrs > H:
                low = mid
            else:
                high = mid
                
        if self.calc_hours(piles, low) <= H:
            return low
        if self.calc_hours(piles, high) <= H:
            return high
    
    @staticmethod
    def calc_hours(piles, K):
        return int(sum(math.ceil(pile / float(K)) for pile in piles))


import math

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        minn = max(1, int(math.floor(sum(piles) / float(H))))
        l = minn
        r = max(piles)
        while l <= r:
            m = l + (r-l)//2
            if calc_h(piles, m) > H:
                l = m + 1
            else:  # calc_h(piles, m) <= H
                if m == minn or calc_h(piles, m-1) > H:
                    return m
                r = m - 1

def calc_h(piles, K):
    h = [p // K + (p%K > 0) for p in piles]
    return int(sum(h))


import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def compute_hours(piles, K):
            ret = 0
            for p in piles:
                ret += math.ceil(p / K)
            return ret
        
        ## descending, larger K, smaller hours; smaller K, larger hours
        ## find smallest K, where h <= H
        ## result K - 1 should be invalid, since K is the smallest valid value
        lo = 1
        hi = sum(piles)
        while lo < hi:
            mid = lo + (hi - lo + 1) // 2
            val = compute_hours(piles, mid)
            if val <= H: ## K might be smaller
                hi = mid - 1
            else: ## too small
                lo = mid
        if compute_hours(piles, hi) <= H: ## happens when hi == original lo
            return hi
        else:
            return hi + 1

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lo = 1
        hi = max(piles)
        
        while lo < hi:
            mid = (hi - lo) // 2 + lo
            if sum([math.ceil(i/mid) for i in piles]) > H:
                lo = mid + 1
            else:
                hi = mid
        return lo


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lower_bound = 1
        upper_bound = sum(piles)
        
        while lower_bound < upper_bound:
            speed = (lower_bound + upper_bound) // 2
            if self.can_finish(piles, speed, H):
                upper_bound = speed
            else:
                lower_bound = speed + 1
                
        return upper_bound
    
    def can_finish(self, piles, speed, h):
        hours = 0
        for bananas in piles:
            hours += math.ceil(bananas / speed)
                
        return hours <= h


import math

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        n = len(piles)
        s = sum(piles)
        
        if H == n:
            return max(piles)
        
        if H > s:
            return 1
        
        k = s // H
        i = 0
        while True:
            t = 0
            for j in range(len(piles)):
                t += math.ceil(piles[j] / k)
            if t <= H:
                return k
            k += 1
        
        return 0

class Solution:
    def minEatingSpeed(self, piles, H):
        lo, hi = 1, max(piles)
        
        while lo <= hi:
            K = lo + ((hi - lo) >> 1)
            if self.countTimeEatAllAtSpeed(
                    K, piles) <= H:  # count time to eat all bananas at speed K
                hi = K - 1
            else:
                lo = K + 1
        return lo
    
    def countTimeEatAllAtSpeed(self, K, piles):
        countHours = 0  # hours take to eat all bananas
        
        for pile in piles:
            countHours += pile // K
            if pile % K != 0:
                countHours += 1
        return countHours

class Solution:
    def hours(self,piles,k):
        cnt=0
        for p in piles:
            if p<=k:
                cnt=cnt+1
            else:
                cnt=cnt+ p//k +1
        return cnt
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if len(piles)==1:
            return 1+piles[0]//H
        l=0
        r=max(piles)
        while(l<=r):
            mid=(l+r)//2
            hrs=self.hours(piles,mid)
            if (hrs<=H):
                ans=mid
                r=mid-1
            else:
                l=mid+1
        return ans
        
                


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        
        left = 1
        right = max(piles)
        
        
        while right > left:
            
            speed = int((left+right)/2)
            
            total_hours = 0
            
            for i in piles:
                total_hours += math.ceil(i/speed)
                
                
            if(total_hours > H):
                left = speed + 1
            else:
                right = speed
                
        return left
                
                
                


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        max_k = 0
        for value in piles:
            max_k = max(max_k, value)
        
        def possible(k):
            hours = 0
            for item in piles:
                hours += math.ceil(item / k)
                if hours > H:
                    return False
            if hours <= H:
                return True
            return False
        
        def binary_search(low, high):
            mid = low + (high - low)//2
            if possible(low):
                return low
            elif possible(mid):
                return binary_search(low, mid)
            else:
                return binary_search(mid+1, high)
        
        def binary_search_iter(low, high):
            while low < high:
                mid = low + (high - low)//2
                if possible(low):
                    return low
                elif possible(mid):
                    high = mid
                else:
                    low = mid + 1
            return high
        
        return binary_search_iter(1, max_k)

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lo = 1
        hi = max(piles)
        ans = 0
        while hi >= lo:
            mid = (lo + hi) // 2
            if self.check(mid, piles, H):
                ans = mid
                hi = mid - 1
            else:
                lo = mid + 1  
        return ans
    
    def check(self, mid, piles, H):
        i = 0
        count = 0
        new = piles[::]
        while i < len(new):
            if count > H:
                return False
            if mid >= new[i]:
                count += 1
                i += 1
            else:
                count += new[i] // mid + 1
                i += 1
        if count > H:
            return False
        return True
                
                
            
            
            
            
            
            
            
    
    
        


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if H == len(piles):
            return max(piles)
        
        l = 1
        r = max(piles) + 1
        while l < r:
            m = l + (r - l) // 2
            if self.minHours(piles, m) <= H:
                r = m
            elif self.minHours(piles, m) > H:
                l = m + 1
        return l
        
        
    def minHours(self, piles, k):
        h = 0
        for p in piles:
            if p % k == 0:
                h += p // k
            else:
                h = h + p // k + 1
        return h
        


import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        l = 1
        r = max(piles)
        while l <= r:
            m = l + (r-l)//2
            if calc_h(piles, m) > H:
                l = m + 1
            else:  # calc_h(piles, m) <= H
                if m == 1 or calc_h(piles, m-1) > H:
                    return m
                r = m - 1

def calc_h(piles, K):
    h = [math.ceil(p / K) for p in piles]
    return int(sum(h))


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:


        min_speed = 1
        max_speed = sorted(piles)[-1]
        while min_speed <=max_speed :
            #print('min_speed',min_speed)
            #print('max_speed',max_speed)

            pivot = min_speed + (max_speed - min_speed)//2
            #print('current_speed',pivot)

            hours = [math.ceil(x/pivot) for x in piles]
            #print('hours=',hours)
            r=0
            for x in hours:
                if x ==0:
                    #print('if_x',x+1)
                    r+=1
                else:
                    #print('else_x',x)
                    r+=x
            #print('r',r)
            #print()
            if r == H:
                return pivot
            elif min_speed==max_speed and r>=H:
                return pivot+1
            #elif min_speed==max_speed and r < H:
            #    min_speed = pivot+1
            elif r < H:
                max_speed = pivot-1

            elif r > H:
                min_speed = pivot+1
        return pivot

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def cnt(k,piles):
            ans=0
            for p in piles:
                ans+=math.ceil(p/float(k))
            return int(ans)
        piles.sort()
        l=1
        h=piles[-1]
        mid=(l+h)//2
        while l<=h:
            s=cnt(mid,piles)
            if s<=H:
                h=mid-1
            else:
                l=mid+1
            mid=(l+h)//2
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def valid(mid):
            if mid==0:
                return False
            hours = 0
            for i in piles:
                if i<mid:
                    hours+=1
                else:
                    hours+=math.ceil(i/mid)

            return hours<=H
        
        if not piles:
            return 0
        
        piles = sorted(piles)
        s,e = 0,sum(piles)
        ans = -1
        while s<=e:
            mid = (s+e)//2
            if valid(mid):
                ans = mid
                e = mid-1
            else:
                s = mid+1
                
        return ans


class Solution:
    def get_hours(self, piles, k):
        ans = 0
        for x in piles:
            if x%k==0:
                ans+=x//k
            else:
                ans+=int(x//k)+1
        return ans
    
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        n,max_val = len(piles), max(piles)
        if H<n:
            return 1<<31
        start,end=1, max_val
        while start<=end:
            mid = (end-start)//2+start
            h = self.get_hours(piles, mid)
            if h<=H:
                end=mid-1
            else:
                start=mid+1
                
        #print(start)
        return start if start<=max_val else start-1

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def is_smaller_equal_H(piles, K, H):
            ret = 0
            for p in piles:
                ret += math.ceil(p / K)
                if ret > H:
                    return False
            return True
        
        ## descending, larger K, smaller hours; smaller K, larger hours
        ## find smallest K, where h <= H
        ## result K - 1 should be invalid, since K is the smallest valid value
        lo = 1
        hi = sum(piles)
        while lo < hi:
            mid = lo + (hi - lo + 1) // 2
            flag = is_smaller_equal_H(piles, mid, H)
            if flag: ## K might be smaller
                hi = mid - 1
            else: ## too small
                lo = mid
        if is_smaller_equal_H(piles, hi, H): ## happens when hi == original lo
            return hi
        else:
            return hi + 1

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        
        # bananas=0
        
        def isValid(mid):
            hours=0
            for banana in piles:

                div=math.ceil(banana/mid)
                hours+=div
                if  hours>H:
                    return False
            return True
        
        def binsearch():
            low=1
            high=sum(piles)  
            while low < high:   
                mid=low+(high-low)//2
                # print(isValid(mid),mid)
                if isValid(mid):
                    high=mid
                else:
                    low=mid+1
            return low
        total=sum(piles)
        return binsearch()
                    


from typing import List
from math import ceil
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def get_hours(piles, K):
            total = 0
            for num in piles:
                total += ceil(num / K)
            return total
        
        left, right = 1, max(piles)
        while left < right:
            mid = left + (right - left) // 2
            if get_hours(piles, mid) > H:
                left = mid + 1
            else:
                right = mid
                
        return left

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def feasible(bananas):
            hour = 0
            for pile in piles:
                hs, left = divmod(pile, bananas)
                hour += hs + (left > 0)
            return hour <= H
            
        l = 1
        r = sum(piles)
            
        while l < r:
            mid = (l+r)>>1
            if feasible(mid):
                r = mid
            else:
                l = mid + 1
        return l

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        start, end = 1, max(piles)
        while start+1 < end:
            mid = (start+end) // 2
            if self.is_feasible(piles, H, mid) == False:
                start = mid + 1
            elif self.is_feasible(piles, H, mid) == True:
                end = mid
        if self.is_feasible(piles, H, start):
            return start
        else:
            return end
        
    
    def is_feasible(self, piles, H, speed):
        res = 0
        for i in piles:
            res += math.ceil(i/speed)
        if res <= H:
            return True
        else:
            return False
        
        


import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def check(avg):
            return sum(math.ceil(i/avg) for i in piles)<=H
        hi,lo=max(piles),1
        while lo<hi:
            mid=(lo+hi)//2
            if check(mid):
                hi=mid
            else:
                lo=mid+1
        return hi
        
1        


import math

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        lo = int(math.ceil(sum(piles) / H))
        hi = sum(piles)
        # print(hi)
        
        hours = lambda j: sum([int(math.ceil(i / j)) for i in piles])

        out = -1
        while lo <= hi:
            mid = (lo + hi) // 2
            res = hours(mid)   
            # print(res, mid)
            
            if res <= H:
                out = mid
            if res <= H:
                hi = mid - 1
            else:
                lo = mid + 1
                
        return out

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        low=1
        ans=[0]
        high=max(piles)
        h=[H]
     
        
        def check(speed,piles):
            cost=0
            
            for i in piles:
                cost+=math.ceil(i/speed)
                
                if cost>h[0]:
                    return False
            return True
            
        def binary(low,high):
            
            if low>high:
                return high
            mid=(low+high)//2
           
            if check(mid,piles):
                ans[0]=mid
              
                binary(low,mid-1)
            else:
                 
                
                binary(mid+1,high)
        binary(low,high)
        return ans[-1]

from math import ceil
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def doesViolate(mid):
            requiredHour = 0
            for i in range(0, len(piles)):
                if mid > piles[i]:
                    requiredHour+=1
                else:
                    requiredHour += math.ceil(piles[i]/mid)
            if requiredHour > H:
                return True
            else: return False
        low = 1
        high = max(piles)
        
        while (low < high):
            mid = (low+high) // 2
            if doesViolate(mid) == True:
                low = mid + 1
            else:
                high = mid
        return low


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        from math import ceil
        left = 1
        right = max(piles) + 1
        timeConsumption = lambda speed: sum(ceil(pile / speed) for pile in piles)
        while left < right:
            mid = left + (right - left) // 2
            time = timeConsumption(mid)
            if time > H: left = mid + 1
            else: right = mid
        return left

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def feasible(bananas):
            hour = 0
            for pile in piles:
                hs, left = divmod(pile, bananas)
                hour += hs + (left > 0)
                if hour > H:
                    return False
            return hour <= H
            
        l = 1
        r = sum(piles)
            
        while l < r:
            mid = (l+r)>>1
            if feasible(mid):
                r = mid
            else:
                l = mid + 1
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        l = max(sum(piles)//H, 1)
        h = max(piles)
        while l < h:
            mid = (l + h) // 2
            timeL = self.timeTaken(piles, l)
            timeMid = self.timeTaken(piles, mid)
            if timeL <= H:
                return l
            elif timeMid <= H:
                h = mid
                timeH = timeMid
                l += 1
            else:
                l = mid + 1
        return l
    def timeTaken(self, piles, n):
        summ = 0
        for v in piles:
            summ += v // n
            if v % n:
                summ += 1
        return summ
                


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # 14:25-
        if H == len(piles):
            return max(piles)
        elif sum(piles) <= H:
            return 1
        
        cntr = collections.Counter(piles)
        lst = set()
        for key in cntr.keys():
            lst.add((key, cntr[key]))
        
        s = 2
        e = max(piles) - 1
        while s <= e:
            K = int((s + e) / 2)
            total = 0
            for pile, n in lst:
                q, r = divmod(pile, K)
                if r:
                    total += (q + 1) * n
                else:
                    total += q * n
                
                if total > H:
                    break
                    
            # fast
            if total <= H:
                e = K - 1
            #slow
            else:
                s = K + 1
        
        return s

from math import ceil

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        hi_fail = 0
        low_pass = max(piles)
        if len(piles) == H:
            # O(n)
            return low_pass

        # O(n*log n)
        piles.sort(reverse=True)
        speed = low_pass // 2
        while low_pass - hi_fail > 1:
            # O(m where m <= n)
            for i, num_bananas in enumerate(piles):
                if num_bananas <= speed:
                    break
            else:
                i += 1

            if not self.can_eat_all(piles, H, speed, i):
                hi_fail = speed
            else:
                low_pass = speed


            speed = (low_pass + hi_fail) // 2

        return low_pass

    def can_eat_all(self, piles, hours, speed, stop_ind):
        # O(l)
        extra_hours = hours - len(piles)
        for i in range(stop_ind):
            hours_needed = int(ceil(piles[i] / speed))
            extra_hours -= (hours_needed - 1)
            if extra_hours < 0:
                return False

        if len(piles) == 1 and extra_hours == 0:
            return False

        return True


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        left = 1
        right = max(piles)
        while left + 1 < right:
            mid = left + (right-left)//2
            if self.possible(piles, H, mid):
                right = mid
            else:
                left = mid
        if self.possible(piles, H, left):
            return left
        return right
            
        
    def possible(self, piles, H, K):
        time = 0
        for p in piles:
            time += math.ceil(p/K)
        return time <= H

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def finishable(piles, H, eatRate) -> bool:
            numHours = 0
            for pile in piles:
                numHours += ceil(pile / eatRate)
            
            return numHours <= H
        
        left, right = 1, max(piles)
        while left < right:
            mid = left + (right - left) // 2
            
            if finishable(piles, H, mid):
                right = mid
            else:
                left = mid + 1
            
        return left

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        right = 10**9
        left = 1
        piles.sort()
        while left + 1 < right:
            mid = (left + right)//2
            if self.canEatAll(piles, mid, H):
                right = mid
            else:
                left = mid
        return left if self.canEatAll(piles, left, H) else right
        

    def canEatAll(self, piles, speed, H):
        res = 0
        for pile in piles:
            res += (pile - 1)//speed + 1
        return res <= H


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lower = 1
        upper = max(piles)
        
        while lower < upper:
            mid = (lower+upper)//2
            if sum(p//mid + 1 if p%mid else p//mid for p in piles) > H:
                lower = mid + 1
            else:
                upper = mid
                
        return upper


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        s, e = 1, max(piles)
        minK = float('inf')
        while s <= e:
            m = (s + e) // 2
            if self.eat(piles, m) > H:
                s = m + 1
            else:
                minK = min(minK, m)
                e = m - 1
        return minK
        
    def eat(self, piles, K):
        ret = 0
        for p in piles:
            ret += math.ceil(p / K)
        return ret

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if len(piles) == 1:
            div, rem = divmod(piles[0], H)
            if rem == 0:
                return div
            else:
                return div + 1
        left = 0
        right = sum(piles)
        while left < right:
            mid = (left + right) // 2
            if self.CalcTime(piles, mid, H):
                right = mid
            else:
                left = mid + 1
        return left
        
    def CalcTime(self, piles, K, H):
        h = 0
        for p in piles:
            div, rem = divmod(p, K)
            h += div
            if rem > 0:
                h += 1
            if h > H:
                return False
        return h <= H


class Solution:
    def time_taken(self, piles, n):
        return sum(v // n + (1 if v % n else 0) for v in piles)
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lo = max(1, sum(piles) // H)
        hi = max(piles)
                    
        t_hi = self.time_taken(piles, hi)
        
        while lo < hi:
            
            mid = (lo + hi) // 2
            
            t_lo = self.time_taken(piles, lo)
            t_mid = self.time_taken(piles, mid)
            
            if t_lo <= H:
                return lo
            elif t_mid <= H:
                hi, t_hi = mid, t_mid
                lo += 1
            else:
                lo = mid + 1
                
        return lo
    #https://leetcode.com/problems/koko-eating-bananas/discuss/804478/Python-Binary-Search-98
        
        




class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def ifeatK(k):
            hour = 0
            for pile in piles:
    #是math.ceil 不是ceiling            
                hour += math.ceil(pile/k)
            return hour
        
        start =1 
        end = sum(piles)
        
        while start +1 <end:
            mid = (start+end)//2
            if ifeatK(mid) <H:
                end = mid
            elif ifeatK(mid)>H:
                start = mid
            else:
  #不应该 找到mid,就return，应该继续
                end= mid
   #     print(start,end)
        if ifeatK(start)>H:
            return end
        if ifeatK(start)==H:
            return start
        if ifeatK(end)==H:
            return end
        return start


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        min_speed = 1
        max_speed = max(piles)
        while min_speed <=max_speed :
            pivot = min_speed + (max_speed - min_speed)//2  
            hours = [math.ceil(x/pivot) for x in piles]
            r=0
            
            for x in hours:
                if x ==0:
                    r+=1
                else:
                    r+=x
                    
            if r == H:
                return pivot
            elif min_speed==max_speed and r>=H:
                return pivot+1
            elif r < H:
                max_speed = pivot-1
            elif r > H:
                min_speed = pivot+1
                
        return pivot

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        N = len(piles)
        
        start = 1
        end = max(piles)
        
        while start + 1 < end:
            mid = start + (end - start) // 2
            
            if self._can_complete(piles, mid, H):
                end = mid
            else:
                start = mid
                
        if self._can_complete(piles, start, H):
            return start
        else:
            return end
        
    def _can_complete(self, piles, K, H):
        i = 0
        N = len(piles)
        
        c = 0
        for d in piles:
            c += math.ceil(d / K)
            
        return c <= H


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # 14:25-
        if H == len(piles):
            return max(piles)
        elif sum(piles) <= H:
            return 1
        
        cntr = collections.Counter(piles)
        
        s = 2
        e = max(piles) - 1
        while s <= e:
            K = int((s + e) / 2)
            total = 0
            for pile in cntr.keys():
                q, r = divmod(pile, K)
                if r:
                    total += (q + 1) * cntr[pile]
                else:
                    total += q * cntr[pile]
                
                if total > H:
                    break
                    
            # fast
            if total <= H:
                e = K - 1
            #slow
            else:
                s = K + 1
        
        return s

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:  
        # piles = [30,11,23,4,20]
        # H = 6
                
#         piles =[332484035,524908576,855865114,632922376,222257295,690155293,112677673,679580077,337406589,290818316,877337160,901728858,679284947,688210097,692137887,718203285,629455728,941802184]
        
#         H = 823855818
        
        def sop(A, H, K):  
            if (K==0):
                return False
            count = 0 
            for i in A:   
                if (i%K == 0):
                    count += i//K
                else: 
                    count += i//K +1
                
            if count <= H:
                return True 
            
            return False
                            
        l = sum(piles)//H 
        r = max(piles) 
        print((l, r))
        
        print((sop(piles,H,l)))
        
        if len(piles) == 1:
            return l+1
        
        m = (l+r)//2
        while (l<=r):
            # print(m)
            if (sop(piles,H,l) == False) and (sop(piles,H,l+1) == True):
                return l+1 
            
            if (sop(piles,H,r-1) == False) and (sop(piles,H,r) == True):
                return r 
            
            if sop(piles,H,m) == False:
                l = m 
                m = (l+r)//2
            else: 
                r = m 
                m = (l+r)//2 
                
                
                
        
            
            
            
        
        
        
            
            


class Solution:
    def canEat(self, piles, bananas, H):
        cur_H = 0
        for pile in piles:
            if pile % bananas == 0:
                cur_H += pile // bananas
            else:
                cur_H += pile // bananas + 1
        if cur_H > H:
            return False
        return True
        
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        min_speed = 1
        max_speed = max(piles)
        while(min_speed < max_speed):
            mid = (min_speed + max_speed) // 2
            if self.canEat(piles, mid, H):
                max_speed = mid
            else:
                min_speed = mid + 1
        return min_speed

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        l, r = 1, max(piles)
        while l <= r:
            m = l + (r-l)//2
            if self.speedBalancer(piles, m) > H:
                l = m + 1
            elif self.speedBalancer(piles, m) <= H:
                r = m - 1
        return l
                
                
    def speedBalancer(self, piles, target):
        h = 0
        for i in piles:
            h += i // target
            if i % target != 0:
                h += 1
        return h

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def condition(arr, k, h):
            res = 0
            for i in arr:
                res += math.ceil(i/k)
            if res <= h:
                return True
            return False
        
        l, r = 1, max(piles)
        while l < r:
            m = l + (r-l)//2
            if condition(piles, m, H):
                r = m
            else:
                l = m + 1
        
        return l

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        low=1
        ans=[0]
        high=max(piles)
        h=[H]
        def check(speed,piles):
            cost=0
            
            for i in piles:
                cost+=math.ceil(i/speed)
                
                if cost>h[0]:
                    return False
            return True
            
        def binary(low,high):
            
            if low>high:
                return high
            mid=(low+high)//2
           
            if check(mid,piles):
                ans[0]=mid
              
                binary(low,mid-1)
            else:
                 
                
                binary(mid+1,high)
        binary(low,high)
        return ans[-1]

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        n = len(piles)
        if n >= H:
            return max(piles)
        def check(m):
            ret = 0
            for p in piles:
                ret += p//m + (p%m!=0)
            return ret
        upper = max(piles)
        lo, hi = 1, upper
        while lo<=hi:
            mid = (lo+hi)//2
            if check(mid) <= H:
                hi = mid - 1
            else:
                lo = mid + 1
        return lo


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        
        lo = max(1, sum(piles) // H)
        hi = max(piles)
        
               
        t_hi = self.time_taken(piles, hi)
        
        while lo < hi:
            
            mid = (lo + hi) // 2
            
            t_lo = self.time_taken(piles, lo)
            t_mid = self.time_taken(piles, mid)
            if t_lo <= H:
                return lo
            elif t_mid <= H:
                hi, t_hi = mid, t_mid
                lo += 1
            else:
                lo = mid + 1
                
        return lo
        
        
    def time_taken(self, piles, n):
        
        return sum(v // n + (1 if v % n else 0) for v in piles)

import math

class Solution:
    def cc(self,l,n):
        ans=0
        for i in l:
            ans+=math.ceil(i/n)
        return(ans)
    
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        n = len(piles)
        if H==n:
            return(max(piles))
        else:
            l = math.ceil(sum(piles)/H)-1
            r = max(piles)+1
            while r-l>1:
                pivot = (l+r)//2
                if self.cc(piles,pivot)<=H:
                    r = pivot
                elif self.cc(piles,pivot)>H:
                    l = pivot
                
            return(r)
                
            


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:

        piles.sort()
        l,r = 1,max(piles)
        while l <= r:
            m = (l+r)//2
            if sum([(x-1)//m+1 for x in piles]) > H:
                l = m+1
            elif sum([math.ceil(x/m) for x in piles]) < H:
                r = m-1
            else:
                return m
        return l


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        l = 1
        r=max(piles)
        
        while l<r:
            m =l+(r-l)//2
            
            h=0
            for i in piles:
                h+=math.ceil(i/m)            
            if h>H:
                l=m+1
            else:
                r=m
        return l
    
        # low, high = 1, max(piles)
        # while low < high:
        #     mid = (low + high) // 2
        #     h = 0
        #     for i in piles:
        #         h +=math.ceil(i / mid)
        #     if h > H:
        #         low = mid + 1
        #     else:
        #         high = mid
        # return low


import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # Use binary search to find the smallest rate that Koko can eat bananas
        # and still finish all of them in H hours
        
        def feasible(maxBananas):
            hours = 0
            for pile in piles:
                hours += math.ceil(pile/maxBananas)
    
                if hours > H:
                    return False
            return True
        
        
        left = 1 # Slowest
        right = max(piles) # Fastest
        
        while left < right:
            mid = left + (right - left)//2
            
            if feasible(mid):
                right = mid
            else:
                left = mid + 1
                
        return left

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        '''
        # Can Koko eat all bananas in H hours with eating speed K?
        def possible(K):
            return sum((p-1) / K + 1 for p in piles) <= H

        lo, hi = 1, max(piles)
        while lo < hi:
            mi = (lo + hi) // 2
            if not possible(mi):
                lo = mi + 1
            else:
                hi = mi
        return lo
        '''
        
        
        # solution: use binary guess
        
        
        le = 1
        ri = sum(piles)
        
        def checkHours(speed):
            s = 0
            for item in piles:
                s+=math.ceil(item/speed)
            return s
            '''
            sum_hours = 0
            for i in piles:
                bananas =  i
                hours = 0
                while True:
                    bananas = bananas - speed
                    hours += 1
                    if bananas <= 0: # bug only <
                        break
                sum_hours += hours
            return sum_hours
            '''
                        
        
        while le + 1 < ri:
            mid = le + (ri - le)//2
            result = checkHours(mid)
            if result <= H : # decrease speed
                ri = mid
            else: # increase speed
                le =  mid
                
        result = checkHours(le)
 
        if result <= H: # changed to <= H
            return le
        else:
            return ri



class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        left = 1
        right = max(piles)
        while left < right:
            mid = (left+right)//2
            
            hours = 0
            s = i = 0
            rem = 0
            while i<len(piles):
                hours += int(math.ceil(piles[i]/mid))
                i += 1
            # print(mid, hours)
            if hours <= H:
                right = mid
            else:
                left = mid+1
        return left

from math import ceil

def count_hr(piles, k):
    return sum([ceil(p / k) for p in piles])

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if len(piles) > H:
            return
        lo, hi = 1, max(piles)
        while lo <= hi:
            mid = (lo + hi) // 2
            if count_hr(piles, mid) > H:
                lo = mid + 1
            elif count_hr(piles, mid) <= H:
                hi = mid - 1
        
        return lo

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def is_feasible(rate,H,piles):
            
            count=0
            for i in range(len(piles)):
                count+=piles[i]//rate
                
                if piles[i]%rate!=0:
                    count+=1
                
                if count>H:
                    return False
            
            return True
    
    
        
        l=1
        h=sum(piles)
        ans=float('inf')
        
        while l<=h:
            mid=(l+h)//2
            
            if is_feasible(mid,H,piles):
                ans=min(ans,mid) 
                h=mid-1
            
            else:
                l=mid+1
        
        return ans
            
            
                    


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        ceiling = lambda x,y : (x+y-1)//y

        def timeTaken(v):
            # total time taken if Koko eat with v speed
            totalTime = 0
            for p in piles: totalTime += ceiling(p, v)
            return totalTime
        
        def binarySearch(s, e, up_bound):
            # find maximum index that less or equal then up_bound, index s~e
            if(s == e): return s
            m = (s+e)//2
            if(timeTaken(m) <= up_bound):
                return binarySearch(s,m, up_bound)
            else: 
                return binarySearch(m+1, e, up_bound)   
        
        pmax = 1
        for p in piles: pmax = max(pmax, p)
        return binarySearch(1, pmax, H)

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def can_finish(k):
            hours = 0
            for pile in piles:
                div = pile//k
                hours += div
                if pile%k:
                    hours += 1
                # print(pile, k, pile//k, pile%k, hours)
            return hours<=H
        
        left, right = 1, max(piles)
        while left < right:
            mid = (left+right)//2
            if can_finish(mid):
                right = mid
            else:
                left = mid+1
        return left

        
        
'''
3 6 7 11
1 2 3 4 5 6 7 8 9 10 11
mid = 6
hours = 1+1+2+2 6<=8
mid = 3
hours = 1+2+3+4 10<=8
mid = 4
hours = 1+2+2+3 8<=8
mid = 3
hours = 1+2+3+4 10<=8
mid = 3
mid = 4

'''

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lo = max(1, sum(piles) // H)
        hi = max(piles)
                    
        t_hi = self.time_taken(piles, hi)
        
        while lo < hi:
            
            mid = (lo + hi) // 2
            
            t_lo = self.time_taken(piles, lo)
            t_mid = self.time_taken(piles, mid)
            
            if t_lo <= H:
                return lo
            elif t_mid <= H:
                hi, t_hi = mid, t_mid
                lo += 1
            else:
                lo = mid + 1
                
        return lo
        
        
    def time_taken(self, piles, n):
        
        return sum(v // n + (1 if v % n else 0) for v in piles)


class Solution:
    def minEatingSpeed(self, piles, H):
        lo, hi = 1, max(piles)
        
        while lo <= hi:
            K = (lo+hi)//2
            if self.countTimeEatAllAtSpeed(
                    K, piles) <= H:  # count time to eat all bananas at speed K
                hi = K - 1
            else:
                lo = K + 1
        return lo
    
    def countTimeEatAllAtSpeed(self, K, piles):
        countHours = 0  # hours take to eat all bananas
        
        for pile in piles:
            countHours += pile // K
            if pile % K != 0:
                countHours += 1
        return countHours

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def time_needed(piles, time):
            return sum(p//time + (1 if p%time else 0) for p in piles)
        
        lower = max(sum(piles)//H, 1)
        upper = max(piles)
        
        while lower < upper:
            time_lower = time_needed(piles, lower)
            if time_lower <= H:
                return lower
            
            mid = (lower+upper)//2
            time_mid = time_needed(piles, mid)
            if time_mid <= H:
                upper = mid
            else:
                lower = mid+1
                
        return lower

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def is_valid(speed):
            curr = 0
            for n in piles:
                q, r = divmod(n, speed)
                if r:
                    q += 1
                curr += q
                if curr > H:
                    return False
            return True
            
        l, r = 1, max(piles)
        res = -1
        while l <= r:
            m = l + (r - l) // 2
            if is_valid(m):
                res = m
                r = m - 1
            else:
                l = m + 1
        return res

import math

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def possible(K):
            return sum(math.ceil(p/K) for p in piles) <= H
        
        low = 1
        high = max(piles) + 1
        
        while low < high:
            mid = low + ((high - low) // 2)
            if possible(mid):
                high = mid
            else:
                low = mid + 1
                
        return low

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def can_finish(k):
            h = 0
            for p in piles:
                d, r = divmod(p, k)
                if r:
                    d += 1
                h += d
            return h <= H
        l = 1
        r = max(piles)
        while l < r:
            m = (l + r) // 2
            if can_finish(m):
                r = m
            else:
                l = m + 1
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def is_ok(piles, H, mid):
            sum = 0
            for i in range(len(piles)):
                if piles[i] <= mid:
                    sum += 1
                else:
                    sum += math.ceil(piles[i] / mid)
            return sum <= H
        
        ok = sum(piles)
        ng = 0
        while (abs(ok - ng) > 1):
            mid = (ok + ng) // 2
            if is_ok(piles, H, mid):
                ok = mid
            else:
                ng = mid
        return ok

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lo, hi = 1, 1000000001
        ans = -1
        N = len(piles)
        
        def poss(val):
            cnt = 0
            
            for n in range(N):
                cnt += math.ceil(piles[n] / val)
            
            if cnt <= H:
                return True
            return False
        
        
        while lo <= hi:
            mid = lo + (hi - lo) // 2
            if poss(mid):
                ans = mid
                hi = mid - 1
            else:
                lo = mid + 1
        
        return ans



class Solution:
    def minEatingSpeed(self, piles, H):
        start = sum(piles)//H+1
        while start<=max(piles):
            suplus = sum(map(lambda x:(start - x%start)%start,piles))
            if suplus + sum(piles) <= start*H:
                return start
            else:
                start += 1
        return max(piles)

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        
        lo = max(1, sum(piles) // H)
        hi = max(piles)
                    
        #t_hi = self.time_taken(piles, hi)
        
        while lo < hi:
            
            mid = (lo + hi) // 2
            
            t_lo = self.time_taken(piles, lo)
            t_mid = self.time_taken(piles, mid)
            
            if t_lo <= H:
                return lo
            elif t_mid <= H:
                #hi, t_hi = mid, t_mid
                hi = mid
                lo += 1
            else:
                lo = mid + 1
                
        return lo
        
        
    def time_taken(self, piles, n):
        
        return sum(v // n + (1 if v % n else 0) for v in piles)


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def time(val):
            t = len(piles)
            for pile in piles:
                t += (pile - 1) // val
            return t
        
        s = sum(piles)
        l, r = math.ceil(s / H), math.ceil(s / (H - len(piles) + 1))
        while l <= r:
            mid = l + (r - l) // 2
            t = time(mid)
            if t <= H:
                r = mid - 1
            else:
                l = mid + 1
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        l = max(1,sum(piles)//H)
        r = max(piles)//(H//len(piles)) + 1
        # print(l,r)
        def hours(rate):
            count = 0
            for x in piles:
                count += (x+rate-1)//rate
            return count
                
        while l <= r:
            mid = (l+r)//2
            h = hours(mid)
            if h > H:
                l = mid+1
            else:
                ans = mid
                r = mid-1
        return ans   

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def time_needed(time):
            return sum(p//time + (1 if p%time else 0) for p in piles)
        
        lower = max(sum(piles)//H, 1)
        upper = max(piles)
        
        while lower < upper:
            time_lower = time_needed(lower)
            if time_lower <= H:
                return lower
            
            mid = (lower+upper)//2
            time_mid = time_needed(mid)
            if time_mid <= H:
                upper = mid
                lower += 1
            else:
                lower = mid+1
                
        return lower

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if len(piles) == 1:
            return piles[0]//H if piles[0]%H == 0 else piles[0]//H + 1
        
        l = sum(piles)//H 
        h = max(piles)*len(piles)//H + 1
        
        # def feasible(c):
        #     t = 0
        #     s = 0
        #     for n in piles:
        #         if n <= c: #can finish this pile
        #             t += 1
        #         else: 
        #             t += n//c if n%c == 0 else n//c + 1
        #         #print(n, t)
        #     if t <= H:
        #         return True
        #     return False
        def feasible(k): #from solution, much shorter and cleaner
            return sum((p-1)//k + 1 for p in piles) <= H
        
        while l < h:
            mid = (l+h)//2
            #print(l, h, mid)
            if feasible(mid):
                h = mid #search if smaller capacity possible
            else:
                l = mid + 1
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lenth = len(piles)
        s = ((min(piles)-1)*lenth)//H+1 #向上取整
        m = ((max(piles)-1)*lenth)//H+1
        if int(m)<m:
            m=int(m)+1
        if s==m:return s
        while s<m:
            mid = (s+m)//2
            count = sum([((i - 1) // mid + 1) for i in piles])
            if count>H:
                s=mid+1
            else:
                m=mid
        return s


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def time_needed(time):
            return sum(p//time + (1 if p%time else 0) for p in piles)
        
        lower = max(1, sum(piles)//H)
        upper = max(piles)
        
        while lower < upper:
            time_lower = time_needed(lower)
            if time_lower <= H:
                return lower
            
            lower += 1
            mid = (lower + upper)//2
            time_mid = time_needed(mid)
            if time_mid <= H:
                upper = mid
            else:
                lower = mid + 1
            
            
        return lower


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        k = sum(piles)//H
        if k == 0: return 1 #if H is more than sum of all piles
        while True:
            h = 0
            prev = k
            #print(k)
            for p in piles:
                print(p,k)
                if p > 1:
                    h += (p-1)//k+1
                else:
                    h += 1
                if h > H:
                    #print(k,h)
                    break
            if h <= H:
                return k 
            k += 1

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def possible(K):
            return sum(ceil(pile / K) for pile in piles) <= H
        total = sum(piles)
        lo, hi = ceil(total / H), ceil(total / (H - len(piles) + 1))
        while lo < hi:
            mid = lo + (hi - lo) // 2
            if possible(mid):
                hi = mid
            else:
                lo = mid + 1
        return lo


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        
        lo = max(1, sum(piles) // H)
        hi = max(piles)
        
               
        t_hi = self.time_taken(piles, hi)
        
        while lo < hi:
            
            mid = (lo + hi) // 2
            
            t_lo = self.time_taken(piles, lo)
            t_mid = self.time_taken(piles, mid)
            
            if t_lo <= H:
                return lo
            elif t_mid <= H:
                hi, t_hi = mid, t_mid
                lo += 1
            else:
                lo = mid + 1
                
        return lo
        
        
    def time_taken(self, piles, n):
        
        return sum(v // n + (1 if v % n else 0) for v in piles)

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        n = len(piles)
        piles.sort()
        
        def finish(k): #O(n)
            return sum((p-1)//k+1 for p in piles)<=H 
            
        r = 0
        while r<n:
            if finish(piles[r]):
                break
            else: r += 1
        
        # Then binary search K in piles[l] and piles[r]
        start = 1 if r==0 else piles[0]
        end = piles[r]
        
        while start<end:
            mid = (start+end)//2
            if finish(mid):
                end = mid
            else:
                start = mid+1
        return start
                
                


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if not piles:   return 0
        l,r = 1,max(piles)
        
        def canDo(pace):
            ans = 0
            for v in piles:
                ans -= (-v//pace)
            return ans <= H
        
        while l < r:
            m = (l+r)//2
            if canDo(m):
                r = m
            else:
                l = m+1
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        
        lo = max(1, sum(piles) // H)
        hi = max(piles)
                    
        t_hi = self.time_taken(piles, hi)
        
        while lo < hi:
            
            mid = (lo + hi) // 2
            
            t_lo = self.time_taken(piles, lo)
            t_mid = self.time_taken(piles, mid)
            
            if t_lo <= H:
                return lo
            elif t_mid <= H:
                hi, t_hi = mid, t_mid
                lo += 1
            else:
                lo = mid + 1
                
        return lo
        
        
    def time_taken(self, piles, n):
        
        return sum(v // n + (1 if v % n else 0) for v in piles)


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if not piles:   return 0
        l,r = 1,max(piles)
        
        def canDo(k):
            ans = 0
            for v in piles:
                ans -= (-v//k)  #round up
            return ans <= H
        
        while l<r:
            m = (l+r)//2
            if canDo(m):
                r = m
            else:
                l = m+1
        return l


class Solution:
    def minEatingSpeed(self, piles, H):
        import math
        left = 1
        right = math.ceil(max(piles)*len(piles)/H)
        while left < right:
            mid = left + (right - left)//2
            if self.f(piles, mid) > H:
                left = mid + 1
            else:
                right = mid

        return left

    def f(self, piles, K):
        import math
        hours = 0
        for pile in piles:
            hours += math.ceil(pile/K)
        return hours

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        l, r = 1, max(piles)
        
        while l < r:
            mid = l + (r - l) // 2
            if sum([-pile // mid for pile in piles]) < -H:
                l = mid + 1
            else:
                r = mid
        
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        bananas = sum(piles)
        K = bananas // H + (bananas % H != 0)
        while True:
            if sum([pile // K + (pile % K != 0) for pile in piles]) <= H:
                return K
            K += 1


## class Solution:
##     def minEatingSpeed(self, piles: List[int], H: int) -> int:
class Solution:
    def minEatingSpeed(self, piles: List[int], H:int) -> int:
        
        l, r = 1, max(piles)
        
        while l< r:
            mid = l + (r-l) // 2
            
            if sum([-pile // mid for pile in piles]) < -H:
                
                l = mid +1
            
            else:
                r = mid
        return l
            
            
            
            
            


class Solution():
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def feasible(speed) -> bool:
            # return sum(math.ceil(pile / speed) for pile in piles) <= H  # slower        
            return sum((pile - 1) // speed + 1 for pile in piles) <= H  # faster

        left, right = 1, max(piles)
        while left < right:
            mid = left  + (right - left) // 2
            if feasible(mid):
                right = mid
            else:
                left = mid + 1
        return left

#SELF TRY 10/7/2020
# class Solution:
#     def minEatingSpeed(self, piles: List[int], H: int) -> int:
#         def eat_speed(K, H):
#             banana_per_hour = 0 #This is basically the hour it'll take to eat all the bananas. 
#             #Let's say K = 4 
#             #Pile is 10 
#             #To eat 4 per hour it takes 3 hours 
#             #You can do pile // K -> 10 // 4 = 2  (8 banana in 2 hours)
#             #Then pile % K -> 2 remainder is 2 (so since k is 4 then we can eat all the bananas)
#             for pile in piles: 
#                 banana_per_hour += pile // K
#                 if pile % K != 0: #You can eat all of it takes an extra hour only 
#                     banana_per_hour += 1 
#             return banana_per_hour
            
            
            
#         #inclusive this is what we use for our K value to TRY 
#         left = 1 
#         right = max(piles) 
        
#         while left <= right: 
#             K = left + (right - left) // 2 
#             banana_per_hour = eat_speed(K,H)
#             if banana_per_hour <= H: #this is fine 
#                 right = K - 1 
#             else: #banana_per_hour > H #not possible so we need to increase the number of bananas that Koko can eat.
#                 left = K + 1 
#         return left 
            
            
            
            
        
# class Solution:
#     def minEatingSpeed(self, piles: List[int], H: int) -> int:
       
        
#         def K_speed(K, piles): 
#             hours_to_eat = 0
            
#             for pile in piles: 
#                 hours_to_eat = hours_to_eat + (pile // K)
#                 if pile % K != 0:
#                     hours_to_eat += 1
                    
                    
#                 # if pile % K == 0: 
                
#             return hours_to_eat
        
#         #two cases 
#         # 1 < H 
#         #2 == H 
#         left = 1 
#         right = max(piles)
#         #other way is inclusive ^ 
#         #but left <= right 
#         # and if that's the case right = K - 1 
#         #So if you do it <= you know that AT that point hours to eat is <= H we know that there's a possibility of our CURRENT K being a solution
#         #However in this case you need to do a K - 1 because you are trying to find the next smallest for Koko still eating all bananas.
#         #Because if our RIGHT becomes < our right we are done 
#         while left < right: 
#             K = left + (right - left) // 2 
#             if K_speed(K, piles) <= H: 
#                 right = K
                
#             else: 
#                 left = K + 1
               
                
#         # LEFT has passed your RIGHT BOUND   
#         #inclsuvie or exclusive inclsuive w/ one exclusive
#         #I give you a number that doesn't exist 
#         return left 
    
    
    
#     #BINARY SEARCH 
#     LEFT <= RIGHT: 
        
        
        
#         return LEFT whatever it is your answer 

            
        
        
                
            
        
        
        
        
        
        
        #monkey eats bananas
        #there are N piles of bananas 
        #the i-th pile has piles[i] amount of bananas
        #The guard have gone and will come back in H hours 
        
        #She has a bananas eating per hour speed K 
        #Each hour she chosses some banans and eats the K bannas in that pile 
        
#         1) 
        #If the pile has less than K bananas she eats all of them 
        #And won't eat anymore bananas during the hour 
        
        
        #Monkey eats slow but needs to finish eating all the bananas before the guard comes back
        
        #Return the minimum (int) K s.t she can eat all the bananas within H hours.
        
        
        # 
        #K to try to eat all the piles within that hour 
        


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        left = 1
        right = max(piles)
        while left <= right:
            mid = (left + right) //2
            hours = sum((x - 1) // mid + 1 for x in piles) # 从1开始需要-1
            if hours <= H: # mid越大 ，需要时间越短
                right = mid - 1
            else:
                left = mid + 1
        return left
        
        
        
        
        
        
        
        
        
        
#         def hours(k):
#             count = 0 
#             for x in piles:
#                 count += (x-1)//k + 1 
#             return count 
        
#         left = 1
#         right = max(piles)
#         while left <= right:
#             mid = (left + right)//2 
#             if hours(mid) <= H:  #
#                 right = mid - 1
#             else: 
#                 left = mid + 1 
#         return left 
                
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
#         def hours(k):
#             h = 0
#             for x in piles:
#                 h += (x-1)//k + 1
#             return h 
        
#         left = 1 
#         right = max(piles)  # 最多也就是每次都吃完
#         while left <= right:
#             mid = (left + right)//2
#             if hours(mid) > H:
#                 left = mid + 1 
#             else: 
#                 right = mid -1 
#         return left 
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
#         def hours(k):
#             h = 0 
#             for x in piles : 
#                 h += (x-1)//k + 1 
#             return h 
        
#         left = 1 
#         right = max(piles) 
#         while left <= right: 
#             mid = (left + right)//2
#             if hours(mid) <= H: 
#                 right = mid - 1 
#             else: left = mid + 1 
#         return left 


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
    
#         3 6 7 11 
#         H = 8
#         sumi = 27 
#         mini = 4
#         maxi = max(piles) = 11
        
        # 1 2 3 4 5 6 7 8 10 11
        # func() => 
        # F F F T T T T T T  T 
        mini = 1
        maxi = max(piles)
        ans = 0
        while(mini<=maxi):
            mid = mini+(maxi-mini)//2
            value = sum((p-1)//mid + 1 for p in piles)
            # print(value, mid)
            if value<=H:
                ans = mid
                maxi = mid-1
            else:
                mini = mid+1
        return ans

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # time O(nlogw); space O(1)
        def possible(k):
            return sum((num-1) // k + 1 for num in piles) <= H
        
        left, right = 1, max(piles)
        while left < right:
            mid = (left + right) // 2
            if not possible(mid):
                left = mid + 1
            else:
                right = mid
        
        return left 

class Solution(object):
    def minEatingSpeed(self, piles, H):
        # Can Koko eat all bananas in H hours with eating speed K?
        def possible(K):
            return sum((p-1) // K + 1 for p in piles) <= H

        lo, hi = 1, max(piles)
        while lo < hi:
            mi = (lo + hi) // 2
            if not possible(mi):
                lo = mi + 1
            else:
                hi = mi
        return lo

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def can_finish(piles, K, H):
            return sum([(p + K - 1) // K for p in piles]) <= H
        
        low = 1
        high = max(piles)
        while low < high:
            mid = low + (high - low) // 2
            if can_finish(piles, mid, H):
                high = mid
            else:
                low = mid + 1
        return low

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        l, r = 1, max(piles)
        while l < r:
            m = (l + r) // 2
            if sum((p + m - 1) // m for p in piles) > H: l = m + 1
            else: r = m
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        low, high = 1, max(piles)
        while low < high:
            K = low + (high - low) // 2
            h = sum([(pile - 1) // K + 1 for pile in piles])
            if h <= H:
                high = K
            else:
                low = K + 1
        return low

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        #bananas = sum(piles)
        K = sum(piles) // H + (sum(piles) % H != 0)
        while True:
            hours_needed = 0
            for pile in piles:
                hours_needed += pile // K + (pile % K != 0)
            if hours_needed <= H:
                return K
            K += 1


from math import ceil
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        left,right = 1,max(piles)
        def banana_test(bans):
            return sum([ceil(pile/bans) for pile in piles])<=H
        while left < right:
            mid = left + (right-left)//2
            if banana_test(mid):
                right = mid
            else:
                left = mid + 1
        return left

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def eats(piles, h, k):
            hours = 0
            for pile in piles:
                hours += ((pile - 1) // k + 1)
            return hours <= h
        
        lo = 1
        hi = 10**9
        
        while lo < hi:
            mid = lo + (hi - lo) // 2
            
            if eats(piles, H, mid):
                hi = mid
            else:
                lo = mid + 1
        
        return lo


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def possible(k):
            return sum((num-1) // k + 1 for num in piles) <= H
            
        left, right = 1, max(piles)
        while left < right:
            print((left, right))
            mid = (left + right) // 2
            if not possible(mid):
                left = mid + 1
            else:
                right = mid
        return left


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # Find the first <= in  [> > > > > <= <=]
        n = len(piles)
        low, high = 1, max(piles)
        while (low + 1) < high:
            mid = low + ((high - low) // 2)
            used_hrs = self.calc_hours(piles, mid)
            if used_hrs > H:
                low = mid
            else:
                high = mid
                
        if self.calc_hours(piles, low) <= H:
            return low
        if self.calc_hours(piles, high) <= H:
            return high
    
    @staticmethod
    def calc_hours(piles, K):
        return sum(((pile - 1) // K + 1) for pile in piles)



class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # find smallest k that koko can finish in H hours
        left = 1 
        right = max(piles)
        
        def can(k):
            return sum((p-1)//k + 1 for p in piles) <= H
            
            
        while left < right:
            mid = (left + right) //2 # mid=left<right, left=right
            if can(mid):
                right = mid
            else:
                left = mid + 1

        return right


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def time_used(T):
            return sum(p//T + (1 if p%T else 0) for p in piles)
        
        low = max(sum(piles)//H, 1) 
        if time_used(low) <= H: return low
        high = max(piles)
        
        while low+1 < high:
            mid = (low + high)//2
            if time_used(mid) > H:
                low = mid
            else:
                high = mid
                
        return high

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # Find the first <= in  [> > > > > <= <=]
        n = len(piles)
        low, high = 1, max(piles)
        while (low + 1) < high:
            mid = low + ((high - low) // 2)
            used_hrs = self.calc_hours(piles, mid)
            if used_hrs > H:
                low = mid
            else:
                high = mid
                
        if self.calc_hours(piles, low) <= H:
            return low
        if self.calc_hours(piles, high) <= H:
            return high
    
    @staticmethod
    def calc_hours(piles, K):
        return int(sum(((pile - 1) // K + 1) for pile in piles))



class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lo, hi = 1, max(piles)
        
        while lo<hi:
            mid=(lo+hi)//2
            
            cur_cap, num_hrs = 0, 0
            for p in piles:
                cur_cap = p
                if cur_cap<=mid:
                    num_hrs+=1
                else:
                    num_hrs+=(cur_cap//mid)+1

            if num_hrs>H:
                lo=mid+1
            else:
                hi=mid
        
        return lo


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def simulate(k):
            hours = 0
            for pile in piles:
                hours += ceil(pile / k)
            return hours
        lower = 1
        upper = 1
        for pile in piles:
            upper = max(upper, pile)
        while lower < upper:
            midpoint = (upper + lower) // 2
            if simulate(midpoint) > H:
                lower = midpoint + 1
            else:
                upper = midpoint
        return upper

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def possible(K):
            return sum(math.ceil(p/ K) for p in piles) <= H

        N = len(piles)
        if H == N:
            return max(piles)
        sm = sum(piles)
        lo, hi = int(sm/H)+1, math.ceil(sm/(H-N))
        while lo < hi:
            mi = (lo + hi) // 2
            if not possible(mi):
                lo = mi + 1
            else:
                hi = mi
        return hi


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        l, h = 1, max(piles)
        def canFinish(k):
            hoursTaken = sum([ceil(p / k) for p in piles])
            return hoursTaken <= H
        
        while l < h:
            mid = l + (h - l) // 2
            if canFinish(mid):
                h = mid
            else:
                l = mid + 1
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        low = 1
        high = max(piles)
        while low < high:
            mid = (low + high) // 2
            if sum(pile // mid + (pile % mid > 0) for pile in piles) > H:
                low = mid + 1
            else:
                high = mid
        return low

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        
        def can_eat(x: int, h: int) -> bool:
            hrs = 0
            for p in piles:
                if p<=x:
                    hrs += 1
                else:
                    hrs += (p//x)+1
                if hrs > h: return False
            # print(x, hrs)
            return True
        
        
        low, high = 1, max(piles)
        while low<high:
            mid = low+((high-low)//2)
            if can_eat(mid, H):
                high = mid
            else:
                low = mid+1
        return low

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def count(k):
            
            hours = 0
            for i in range(len(piles)):
                hours += (piles[i] + k - 1) // k
            return hours
                
        l = 1
        r = 1000000000
        while l < r:
            m = l + (r - l) //2
            if count(m) > H:
                l = m + 1
            else:
                r = m
        return l
                


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:

        def possible(K):
            #check if it is possible for K bananas to be finished in H hours
            count = 0
            
            for banana in piles:
                if banana%K==0:
                    count+=banana/K
                else:
                    count += banana//K+1
            
            if count <= H:
                return True
            else:
                return False
                
        
        left,right = 1,max(piles)
        
        while left<=right:
            mid = (left + right) //2
            
            if possible(mid):
                right=mid-1
            else:
                left=mid+1
                
        return left


#SELF TRY 10/7/2020
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def eat_speed(K, H):
            banana_per_hour = 0
            for pile in piles: 
                banana_per_hour += pile // K
                if pile % K != 0: #You can eat all of it 
                    banana_per_hour += 1 
            return banana_per_hour
            
            
            
        #inclusive
        left = 1 
        right = max(piles) 
        
        while left <= right: 
            K = left + (right - left) // 2 
            banana_per_hour = eat_speed(K,H)
            if banana_per_hour <= H: #this is fine 
                right = K - 1 
            else: #banana_per_hour > H #not possible 
                left = K + 1 
        return left 
            
            
            
            
        
# class Solution:
#     def minEatingSpeed(self, piles: List[int], H: int) -> int:
       
        
#         def K_speed(K, piles): 
#             hours_to_eat = 0
            
#             for pile in piles: 
#                 hours_to_eat = hours_to_eat + (pile // K)
#                 if pile % K != 0:
#                     hours_to_eat += 1
                    
                    
#                 # if pile % K == 0: 
                
#             return hours_to_eat
        
#         #two cases 
#         # 1 < H 
#         #2 == H 
#         left = 1 
#         right = max(piles)
#         #other way is inclusive ^ 
#         #but left <= right 
#         # and if that's the case right = K - 1 
#         #So if you do it <= you know that AT that point hours to eat is <= H we know that there's a possibility of our CURRENT K being a solution
#         #However in this case you need to do a K - 1 because you are trying to find the next smallest for Koko still eating all bananas.
#         #Because if our RIGHT becomes < our right we are done 
#         while left < right: 
#             K = left + (right - left) // 2 
#             if K_speed(K, piles) <= H: 
#                 right = K
                
#             else: 
#                 left = K + 1
               
                
#         # LEFT has passed your RIGHT BOUND   
#         #inclsuvie or exclusive inclsuive w/ one exclusive
#         #I give you a number that doesn't exist 
#         return left 
    
    
    
#     #BINARY SEARCH 
#     LEFT <= RIGHT: 
        
        
        
#         return LEFT whatever it is your answer 

            
        
        
                
            
        
        
        
        
        
        
        #monkey eats bananas
        #there are N piles of bananas 
        #the i-th pile has piles[i] amount of bananas
        #The guard have gone and will come back in H hours 
        
        #She has a bananas eating per hour speed K 
        #Each hour she chosses some banans and eats the K bannas in that pile 
        
#         1) 
        #If the pile has less than K bananas she eats all of them 
        #And won't eat anymore bananas during the hour 
        
        
        #Monkey eats slow but needs to finish eating all the bananas before the guard comes back
        
        #Return the minimum (int) K s.t she can eat all the bananas within H hours.
        
        
        # 
        #K to try to eat all the piles within that hour 
        


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        l = 1
        r = max(piles)
        def findTime(count):
            hr = 0
            for p in piles: 
                hr += (p-1)//count+1
                if hr>H:
                    return False
            return True
        
        while l<r:
            mid = l+(r-l)//2
            if findTime(mid):
                r = mid
            else:
                l = mid+1
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def count_hours(k):
            hours = 0
            if k == 1:
                return sum(piles)
            for p in piles:
                hours += p//k
                if p%k != 0:
                    hours += 1
            return hours
        least = 1
        most = max(piles)
        
        while least <= most:
            mid = (most+least)//2
            num_hours = count_hours(mid)
            if num_hours <= H:
                most = mid -1
            else:
                least = mid + 1
        return least


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
       
        
        def K_speed(K, piles): 
            hours_to_eat = 0
            
            for pile in piles: 
                hours_to_eat = hours_to_eat + (pile // K)
                if pile % K != 0:
                    hours_to_eat += 1
                    
                    
                # if pile % K == 0: 
                
            return hours_to_eat
        
        #two cases 
        # 1 < H 
        #2 == H 
        left = 1 
        right = max(piles)
        #other way is inclusive ^ 
        #but left <= right 
        # and if that's the case right = K - 1 
        #So if you do it <= you know that AT that point hours to eat is <= H we know that there's a possibility of our CURRENT K being a solution
        #However in this case you need to do a K - 1 because you are trying to find the next smallest for Koko still eating all bananas.
        while left < right: 
            K = left + (right - left) // 2 
            if K_speed(K, piles) <= H: 
                right = K
                
            else: 
                left = K + 1
               
                
        # LEFT has passed your RIGHT BOUND   
        #inclsuvie or exclusive inclsuive w/ one exclusive
        #I give you a number that doesn't exist 
        return left 
    
    
    
#     #BINARY SEARCH 
#     LEFT <= RIGHT: 
        
        
        
#         return LEFT whatever it is your answer 

            
        
        
                
            
        
        
        
        
        
        
        #monkey eats bananas
        #there are N piles of bananas 
        #the i-th pile has piles[i] amount of bananas
        #The guard have gone and will come back in H hours 
        
        #She has a bananas eating per hour speed K 
        #Each hour she chosses some banans and eats the K bannas in that pile 
        
#         1) 
        #If the pile has less than K bananas she eats all of them 
        #And won't eat anymore bananas during the hour 
        
        
        #Monkey eats slow but needs to finish eating all the bananas before the guard comes back
        
        #Return the minimum (int) K s.t she can eat all the bananas within H hours.
        
        
        # 
        #K to try to eat all the piles within that hour 
        


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        left, right = 1, max(piles)
        while left < right:
            mid = left + (right - left) // 2
            if self.__getEatHours(piles, mid) <= H:
                right = mid
            else:
                left = mid + 1
        return left
    
    def __getEatHours(self, piles, speed):
        hours = 0
        for p in piles:
            hours += p // speed
            if p % speed != 0:
                hours += 1
        return hours

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        left, right = 1, max(piles)
        while left <= right:
            k = left + (right - left) // 2
            if self.finish(k, piles) <= H: # count time to eat all bananas at speed K
                right = k - 1
            else:
                left = k + 1
        return left
    
    def finish(self, k, piles):
        res = 0
        for pile in piles:
            res += pile // k
            if pile % k != 0:
                res += 1
        return res


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lo, hi = 1, max(piles)
        while lo <= hi:
            k = lo + (hi - lo) // 2
            if self.finish(k, piles) <= H: # count time to eat all bananas at speed K
                hi = k - 1
            else:
                lo = k + 1
        return lo
    
    def finish(self, k, piles):
        res = 0
        for pile in piles:
            res += pile // k
            if pile % k != 0:
                res += 1
        return res


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # wants to eat all bananas within H hours
        # K - speed at which eat banana
        # can eat up to pile[i] banana
        # cannot eat 2 piles in 1 hour
        # return min K to eat all bananas in H hours
        
        def get_hours_needed(piles, K):
            hours_needed = 0
            for pile in piles:
                hours_needed += pile // K
                if pile % K != 0:
                    hours_needed += 1
            return hours_needed
        
        lo = 1
        hi = max(piles)
        
        while lo < hi:
            mid = lo + (hi - lo) // 2
            
            if get_hours_needed(piles, mid) > H:
                lo = mid + 1
            else: #hours_needed <= H
                hi = mid
        
        return lo

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        # use binary search to find the correct value
        maxPile = 0
        for i in piles:
            if i > maxPile:
                maxPile = i

        low = 1
        high = maxPile

        minVal = maxPile
        while low <= high:
            middle = (low + high) // 2
            numHours = 0
            for j in piles:
                numHours += j // middle
                if j % middle > 0:
                    numHours += 1

            if numHours <= H:
                minVal = middle
                high = middle - 1
            else:
                low = middle + 1

        return minVal

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        l, r = 1, max(piles)
        while l < r:
            p = l + (r - l) // 2
            if sum(math.ceil(x / p) for x in piles) > H: l = p+1
            else: r = p
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        n = len(piles)
        if not n:
            return -1
        
        def binary_search(l, r):
            nonlocal piles, H
            while l < r:
                mid = (l + r) // 2
                if num_hours(mid) <= H:
                    r = mid
                else:
                    l = mid + 1
            return l
        
        def num_hours(bananas_per_hour):
            nonlocal piles
            res = 0
            for i in piles:
                if bananas_per_hour >= i:
                    res += 1
                    continue
                res += (i // bananas_per_hour)
                res += 1 if i % bananas_per_hour else 0
            return res
        
        return binary_search(1, max(piles))
    
    
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def possible(K):
            return sum(math.ceil(p/K) for p in piles) <= H
        
        lo, hi = 1, max(piles)
        while lo < hi:
            mid = int(lo + (hi-lo)/2)
            
            if not possible(mid):
                lo = mid+1
            else:
                hi = mid
            
        return lo

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def helper(speed):
            h = 0
            for p in piles:
                h += math.ceil(p/speed)
            return h
        if not piles or len(piles) == 0:
            return 0
        start,end = 1,max(piles)
        while start+1 < end:
            mid = start + (end-start)//2
            h = helper(mid)
            if h <= H:
                end = mid
            else:
                start = mid
        return start if helper(start) <= H else end

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if H == len(piles):
            return max(piles)
        def possible(K):
            return sum( math.ceil(p/K) for p in piles) <= H
        lo, hi = 1, max(piles)
        while lo <hi:
            print (lo,hi)
            mi = (lo+hi)//2
            if not possible(mi):
                lo = mi+1
            else:
                hi = mi
        return lo

import math
class Solution:
    
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        #1 2 3 4 5 6 7 8 9 10 11
        
        def possible(x):
            if(x == 0):
                return False
            h = 0
            for i in piles:
                h += math.ceil(i/x)
            return h <= H
        
        
        high = max(piles)
        low = 1
        while(low < high):
            mid = low + (high-low)//2
            if(possible(mid)):
                high = mid
            else:
                low = mid+1
        return low

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        K = sum(piles) // H
        if K == 0:
            K = 1
        while True:
            hours_needed = 0
            for pile in piles:
                hours_needed += pile // K
                if pile % K != 0:
                    hours_needed += 1
            if hours_needed <= H:
                return K
            K += 1


# upper_bound: max(piles)
# lower_bound: ceil(sum(piles) / H)

import math

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        left = math.ceil(sum(piles) / H)
        right = max(piles)
        
        while left <= right:
            middle = (left + right) // 2
            if is_valid(piles, H, middle):
                right = middle - 1
            else:
                left = middle + 1
        
        return left

def is_valid(piles, H, speed):
    hour = 0
    for pile in piles:
        hour += math.ceil(pile / speed)
    return hour <= H


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        if H == len(piles):
            return max(piles)
        else:
            if sum(piles)%H == 0:
                tempMin = sum(piles)//H
            else:
                tempMin = sum(piles)//H+1
            tempMax = max(piles)
            while tempMin != tempMax:
                tempMid = (tempMax-tempMin)//2+tempMin
                if self.ifOk(piles,H,tempMid):
                    tempMax = tempMid
                else:
                    tempMin = tempMid + 1
            return tempMin
    def ifOk(self,piles,H,K):
        hourNeed = 0
        for pile in piles:
            if pile % K == 0:
                hourNeed = hourNeed + pile // K
            else:
                hourNeed = hourNeed + pile // K + 1
            if hourNeed > H:
                return False
        return True

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def canEatAllBananas(speed):
            count=0
            for pile in piles:
                if pile>=speed:
                    count+=pile//speed
                if pile%speed!=0:
                    count+=1
            return count<=H
        
        
        low=1
        high=max(piles)
        
        while low<=high:
            mid=low+(high-low)//2
            if canEatAllBananas(mid):
                high=mid-1
            else:
                low=mid+1
        return low

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def eatingPossible(cap, piles, H):
            h = 0
            for pile in piles:
                h += pile // cap
                if pile % cap != 0:
                    h += 1
                if h > H:
                    return False
            return True
            
        
        piles.sort()
        left = 1
        right = max(piles)
        
        while left < right:
            mid = left + (right-left)//2
            if eatingPossible(mid, piles, H):
                right = mid
            else:
                left = mid + 1
        return left


import math

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        total_bananas = sum(piles)
        left, right = math.ceil(total_bananas / H), max(piles)
        print(left, right)
        while left < right:
            mid = (left + right) // 2
            if not sum([math.ceil(pile/mid) for pile in piles]) <= H:
                left = mid + 1
            else:
                right = mid
        return left

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        
        def isValid(k):
            total = 0
            for pile in piles:
                total += math.ceil(pile/k)
            return total <= H
        
        i,j = 1,max(piles)
        
        while i < j:
            mid = i + (j-i)//2
            if isValid(mid):
                j = mid
            else:
                i = mid+1
        
        return i

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        def time(val):
            t = len(piles)
            for pile in piles:
                t += (pile - 1) // val
            return t
        
        s = sum(piles)
        l, r = math.ceil(s / H), min(max(piles), math.ceil(s / (H - len(piles) + 1)))
        while l <= r:
            mid = l + (r - l) // 2
            t = time(mid)
            if t <= H:
                r = mid - 1
            else:
                l = mid + 1
        return l

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        
        def feasible(threshold):
            count = 0
            for pile in piles:
                
                count += math.ceil(pile/threshold)
                    
                if count > H:
                    return False
            return True
        
        
        left = 1
        right = max(piles)
        
        while left < right :
            
            mid = left + ((right-left)>>1)
            
            if feasible(mid):
                right = mid
            else: left = mid+1
                
        return left

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        min_speed = 1
        max_speed = max(piles)
        while min_speed <=max_speed :
            pivot = min_speed + (max_speed - min_speed)//2  
            r = sum([math.ceil(x/pivot) for x in piles])
            #r=sum(hours)
            if r == H:
                return pivot
            elif min_speed==max_speed and r>=H:
                return pivot+1
            elif r < H:
                max_speed = pivot-1
            elif r > H:
                min_speed = pivot+1
                
        return pivot

import math
class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        left = 1
        right = max(piles)
        while(left < right):
            K = (left+right)//2
            hours = 0
            for pile in piles:
                if(pile <= K):
                    hours += 1
                else:
                    hours += math.ceil(pile/K)
            if(hours > H):
                left = K+1
            else:
                right = K
                
        return left

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        low, high = 1, max(piles)
        
        def isPossible(eatRate):
            total = 0
            for numBanana in piles:
                total += ((numBanana-1)//eatRate) + 1
            return total <= H
        
        while low < high:
            mid = (low + high) // 2
            if isPossible(mid):
                high = mid
            else:
                low = mid + 1
                
        return low

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        n = len(piles)
        if not n:
            return -1
        
        def binary_search(l, r):
            nonlocal piles, H 
            while l < r:
                mid = (l + r) // 2
                if num_hours(mid) <= H:
                    r = mid
                else:
                    l = mid + 1
            return l
            
        def num_hours(k):
            nonlocal n, piles
            res = 0
            for i in range(n):
                num = piles[i]
                if k >= num:
                    res += 1
                    continue
                res += (num // k)
                res += 1 if (num % k) else 0 
            return res
        
        return binary_search(1, max(piles))


class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        minK = 1
        maxK = 0
        for pile in piles:
            if pile > maxK:
                maxK = pile

        low = minK
        high = maxK
        mid = (low+high)//2

        while (low < high):
            testK = mid
            if (self.validK(piles, H, mid)):
                high = mid
            else:
                low = mid+1

            mid = (low+high)//2
        return high

    def validK(self, piles, H, eatspeed):
        hourCount = 0
        for pile in piles:
            hoursUsed = ceil(pile/eatspeed)
            hourCount += hoursUsed
            if hourCount > H:
                return False

        return True

class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        lo = 1
        hi = max(piles)
        def ok(K):
            return sum((1 + (pile - 1) // K) for pile in piles) <= H
        
        while lo < hi:
            mid = (lo + hi) // 2
            if ok(mid):
                hi = mid
            else:
                lo = mid + 1
        return lo