Problem:
 Score: 500 points    Problem Statement  Takahashi will take part in an eating contest. Teams of N members will compete in this contest, and Takahashi's team consists of N players numbered 1 through N from youngest to oldest. The consumption coefficient of Member i is A_i .  In the contest, N foods numbered 1 through N will be presented, and the difficulty of Food i is F_i . The details of the contest are as follows:   A team should assign one member to each food, and should not assign the same member to multiple foods.  It will take x \times y seconds for a member to finish the food, where x is the consumption coefficient of the member and y is the difficulty of the dish.  The score of a team is the longest time it takes for an individual member to finish the food.   Before the contest, Takahashi's team decided to do some training. In one set of training, a member can reduce his/her consumption coefficient by 1 , as long as it does not go below 0 . However, for financial reasons, the N members can do at most K sets of training in total.  What is the minimum possible score of the team, achieved by choosing the amounts of members' training and allocating the dishes optimally?      Constraints   All values in input are integers.  1 \leq N \leq 2 \times 10^5  0 \leq K \leq 10^{18}  1 \leq A_i \leq 10^6\ (1 \leq i \leq N)  1 \leq F_i \leq 10^6\ (1 \leq i \leq N)         Input  Input is given from Standard Input in the following format:  N  K  A_1  A_2  ...  A_N  F_1  F_2  ...  F_N       Output  Print the minimum possible score of the team.        Sample Input 1 3 5
4 2 1
2 3 1      Sample Output 1 2  They can achieve the score of 2 , as follows:   Member 1 does 4 sets of training and eats Food 2 in (4-4) \times 3 = 0 seconds.  Member 2 does 1 set of training and eats Food 3 in (2-1) \times 1 = 1 second.  Member 3 does 0 sets of training and eats Food 1 in (1-0) \times 2 = 2 seconds.   They cannot achieve a score of less than 2 , so the answer is 2 .       Sample Input 2 3 8
4 2 1
2 3 1      Sample Output 2 0  They can choose not to do exactly K sets of training.       Sample Input 3 11 14
3 1 4 1 5 9 2 6 5 3 5
8 9 7 9 3 2 3 8 4 6 2      Sample Output 3 12

Solution (Python):
import math

def read():
    N, K = list(map(int, input().strip().split()))
    A = list(map(int, input().strip().split()))
    F = list(map(int, input().strip().split()))
    return N, K, A, F

def solve(N, K, A, F):
    A = list(sorted(A))
    F = list(reversed(sorted(F)))
    mul = [A[i] * F[i] for i in range(N)]
    smul = list(sorted(mul)) + [9999999999]
    
    def f(x):
        k = 0
        for i in range(N):
            if x < mul[i]:
                k += math.ceil((mul[i] - x) / F[i])
        return k
    
    lb = 0
    ub = 10 ** 12
    while lb < ub:
        x = lb + (ub - lb) // 2
        if f(x) > K:
            
            lb = x+1
        else:
            ub = x
    return lb

if __name__ == '__main__':
    inputs = read()
    print("%d" % solve(*inputs))

Solution (Python):
import numpy as np

N,K=map(int,input().split())
A=list(map(int,input().split()))
F=list(map(int,input().split()))
A.sort()
F.sort(reverse=True)

A=np.array(A)
F=np.array(F)

def judge(x):
    over=np.maximum(A*F-x,0)
    shug=-(-over//F).sum()
    return shug<=K

left=-1
right=10**12*+1
while left+1<right:
    mid=(left+right)//2
    if judge(mid):
        right=mid
    else:
        left=mid
print(right)

Solution (Python):
import sys
input = sys.stdin.readline



N, K = map(int, input().split())
A = list(map(int, input().split()))
F = list(map(int, input().split()))
A.sort()
F.sort(reverse=True)


def check(mid):
    k = K
    
    for i in range(N):
        if A[i] * F[i] > mid:
            
            x = A[i] - mid // F[i]
            k -= x
            
            if k < 0:
                return False
    return True


def main():
    H = []
    for i in range(N):
        H.append(A[i]*F[i])
    
    lb, ub = -1, max(H)
    while ub - lb > 1:
        mid = (lb + ub)//2
        if check(mid):
            ub = mid
        else:
            lb = mid
    print(ub)


if __name__ == '__main__':
    main()

Solution (Python):
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, radians, atan, degrees
from itertools import permutations, combinations, product, accumulate
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from fractions import gcd
from bisect import bisect
import heapq

def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7

N, K = MAP()
A = LIST()
F = LIST()

A.sort(reverse=True)
F.sort()

time = [A[i]*F[i] for i in range(N)]



def is_ok(x):  
	tmp = 0
	for i in range(N):
		if time[i] <= x:
			pass
		else:
			tmp += ceil((time[i]-x)/F[i])
	if tmp > K:
		return False
	else:
		return True

min_ = -1
max_ = 10**18
while min_ + 1 != max_:
	search = (min_+max_)//2
	
	if is_ok(search):
		max_ = search
	else:
		min_ = search

print(max_)

Solution (Python):

import sys
input = lambda: sys.stdin.readline()[:-1]
sys.setrecursionlimit(10**8)
inf = float('inf')
mod = 10**9+7

n,k=map(int,input().split())
A=list(map(int,input().split()))
F=list(map(int,input().split()))
A.sort()
F.sort(reverse=True)
left=0
right=10**12+1
ok=inf
while left<right:
    mid=(left+right)//2
    
    tmp=0
    for i in range(n):
        tmp+=max(0,A[i]-mid//F[i])
    if tmp>k:
        left=mid+1
    else:
        right=mid
        ok=min(ok,mid)
print(ok)

Solution (Python):
from fractions import gcd
from datetime import date, timedelta
from heapq import*
import math
from collections import defaultdict, Counter, deque
import sys
from bisect import *
import itertools
import copy
sys.setrecursionlimit(10 ** 7)
MOD = 10 ** 9 + 7




def main():
    n, k = map(int, input().split())
    a = list(map(int, input().split()))
    f = list(map(int, input().split()))
    a.sort()
    f = sorted(f,reverse=True)

    def ok(v):
        cnt = 0
        sa = 0
        for i in range(n):
            t = a[i]*f[i]
            if v - t >= 0:
                continue
            cnt += a[i] - (v // f[i])
            if cnt > k:
                return False
        
        if cnt <= k:
            return True
        else:
            return False





    l, r = 0, 10 ** 18
    for i in range(80):
        m = (l + r) // 2
        if ok(m):
            r = m
        else:
            l = m
    print(r)

    
            
    

    

    

if __name__ == '__main__':
    main()

Solution (Python):
N, K = [int(x) for x in input().split()]
A = sorted([int(x) for x in input().split()])
F = sorted([int(x) for x in input().split()], reverse=True)
lb = 0
ub = 10 ** 12
def isPossible(M):
    cnt = 0
    
    
    
    for a, f in zip(A, F):
        if (M >= a*f): continue
        cnt += (a*f - M + (f-1)) // f
    return cnt <= K

for i in range(100):
    mid = (lb + ub) // 2
    if (isPossible(mid)):
        ub = mid
    else:
        lb = mid
print(ub)

Solution (Python):
import sys,collections as cl,bisect as bs,heapq as hq
sys.setrecursionlimit(100000)
mod = 10**9+7
Max = sys.maxsize
def l(): 
    return list(map(int,input().split()))
def m(): 
    return map(int,input().split())
def onem(): 
    return int(input())
def s(x): 
    a = []
    aa = x[0]
    su = 1
    for i in range(len(x)-1):
        if aa != x[i+1]:
            a.append([aa,su])
            aa = x[i+1]
            su = 1
        else:
            su += 1
    a.append([aa,su])
    return a
def jo(x): 
    return " ".join(map(str,x))
def max2(x): 
    return max(map(max,x))
def In(x,a): 
    k = bs.bisect_left(a,x)
    if k != len(a) and a[k] ==  x:
        return True
    else:
        return False

def prime_decomposition(n): 
  i = 2
  table = []
  while i * i <= n:
    while n % i == 0:
      n /= i
      table.append(i)
    i += 1
  if n > 1:
    table.append(int(n))
  return table

def make_divisors(n): 
    divisors = []
    for i in range(1, int(n**0.5)+1):
        if n % i == 0:
            divisors.append(i)
            if i != n // i:
                divisors.append(n//i)

    
    return divisors


def ok(x,p):
    kkk = 0
    for i in range(len(x)):
        kkk += max(0,-(-(x[i][0] - p) // x[i][2]))
    return kkk


n,k = m()
a = l()

f = l()

for i in range(n):
    a[i]


a.sort(reverse = True)

f.sort()
co = 0

d = []

for i in range(n):
    d.append([a[i]*f[i],a[i],f[i]])

d.sort(reverse = True)



ll = 0

rr = d[0][0] 


while True:
    mid = (rr+ll)//2

    if rr == mid:
        break

    if ok(d,mid) <= k:
        rr = mid
    else:
        ll = mid+1

print(ll)

Solution (Python):
import numpy as np

def solve():
  N, K = map(int,input().split())
  A = np.array(input().split(), np.int64)
  F = np.array(input().split(), np.int64)

  A.sort()
  F.sort()
  F=F[::-1]
  a_sum = A.sum()
  low, high = -1, 10**13

  while low + 1 < high:
      mid = (low + high) // 2
      if np.minimum(A, mid // F).sum() >= a_sum - K:
          high = mid
      else:
          low = mid
  return high

print(solve())

Solution (Python):

import sys
from math import ceil

_HO = 10**12 + 1

def binary_search(lo=0,ho=_HO):
    if ho-lo==1: return lo

    mid = lo + (ho-lo-1)//2
    if check(mid):
        return binary_search(lo=lo,ho=mid+1)
    else:
        return binary_search(lo=mid+1,ho=ho)

def check(x):
    global k, a, f

    s = 0
    for ai, fi in zip(a,f):
        af = ai * fi
        if af<=x: continue
        s += ceil((af-x)/fi)
        if s>k: return False
    
    return True

n,k = [ int(x) for x in sys.stdin.readline().strip().split() ]
a = [ int(x) for x in sys.stdin.readline().strip().split() ]
f = [ int(x) for x in sys.stdin.readline().strip().split() ]

a.sort()
f.sort(reverse=True)

print(binary_search())

Solution (Python):
import sys
input = sys.stdin.readline
N, K = map(int, input().split())
a = list(map(int, input().split()))
f = list(map(int, input().split()))
a.sort()
f.sort(reverse = True)
res = 0
l = 0
r = 10 ** 12
m = int((l + r) / 2)
c = 0
if sum(a) <= K:
  print(0)
  exit(0)
def check(x):
  k = K + 0
  for i in range(N):
    if a[i] * f[i] > x:
      k -= abs((x - a[i] * f[i]) // f[i])
    if k < 0:
      return False
  return True
while c <= 64:
  m = int((l + r) / 2)
  if check(m) == True:
    r = m
  else:
    l = m
  c += 1
if check(m + 1): print(m + 1)
elif check(max(0, m - 1)): print(m - 1)
else: print(m)

Solution (Python):
import math

def cal(sum_, F, N, K, d):
    count = 0
    for i in range(N):
        if sum_[i] > d:
            count += math.ceil((sum_[i] - d) / F[i])
            if count > K:
                
                return False
    return True


def main():
    N, K = map(int, input().split())
    A = [int(i) for i in input().split()]
    F = [int(i) for i in input().split()]
    A.sort()
    F.sort(reverse=True)
    sum_ = []
    for i in range(N):
        sum_.append(A[i] * F[i])

    right = 10 ** 12
    left = 0
    count = 0
    pre_mid = 0
    while True:
        mid = (right + left) // 2
        if pre_mid == mid:
            break
        if cal(sum_, F, N, K, mid):
            
            right = mid
        else:
            
            left = mid + 1
        pre_mid = mid
        count += 1
    print(mid)


if __name__ == "__main__":
    main()

Solution (Python):
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10 ** 7)
import heapq

N, K = map(int, input().split())
A = list(map(int, input().split()))
F = list(map(int, input().split()))

A = sorted(A)
F = sorted(F, reverse= True)
S = [(-A[i]*F[i], i) for i in range(N)]


def judge(s):
    global N, K
    ksum = 0
    for i in range(N):
        ksum += max(0, -(-(A[i] * F[i] - s) // F[i]))
    if ksum <= K:
        return True
    else:
        return False

lb = -1
ub = 10**13
while lb + 1 < ub:
    mid = (lb + ub) // 2
    if judge(mid):
        ub = mid
    else:
        lb = mid

print(ub)

Solution (Python):
import numpy as np

def test(x, A, F):
	return np.clip(A - x // F, 0, None).sum() <= K

if __name__ == "__main__":
	N, K = map(int, input().split())
	A = np.array([int(a) for a in input().split()])
	F = np.array([int(a) for a in input().split()])
	A = np.sort(A)
	F = np.sort(F)[::-1]
	left = -1
	right = 10**12 + 1
	while left + 1 < right:
		mid = (left + right) // 2
		if test(mid, A, F):
			right = mid
		else:
			left = mid
	ans = right
	print(ans)

Solution (Python):
import sys
input=sys.stdin.readline
N,K=map(int,input().split())
A=list(map(int,input().split()))
A=sorted(A)
F=list(map(int,input().split()))
F=sorted(F,reverse=True)

def is_ok(b):
    k=0
    for a,f in zip(A,F):
        if a>b//f:
            k+=a-(b//f)
            if k>K:
                return False
    return True

ok=10**12+1
ng=-1
while ok-ng>1:
    m=(ok+ng)//2
    if is_ok(m):
        ok=m
    else:
        ng=m

print(ok)

Solution (Python):
import sys
input=sys.stdin.readline
n,k=map(int,input().split())
a=list(map(int,input().split()))
a=sorted(a)
f=list(map(int,input().split()))
f=sorted(f,reverse=True)

def is_ok(b):
    m=0
    for p,q in zip(a,f):
        if p>b//q:
            m+=p-(b//q)
            if m>k:
                return False
    return True

ok=10**12+1
ng=-1
while ok-ng>1:
    m=(ok+ng)//2
    if is_ok(m):
        ok=m
    else:
        ng=m

print(ok)

Solution (Python):
import math

n, k = map(int, input().split())
A = list(map(int, input().split()))
F = list(map(int, input().split()))

def search(x, k, A, F):
    for a, f in zip(A, F):
        time = a * f
        if time <= x:
            continue
        else:
            dif = time - x
            training = int(math.ceil(dif/f))
            k -= training

        if k < 0:
            return False
    return True


A.sort()
F.sort(reverse=True)
r= max([a*f for a, f in zip(A, F)])
l = 0
while l < r:
    candidate = (r+l)//2
    if search(candidate, k, A, F):
        r = candidate
    else:
        l = candidate + 1

print(r)

Solution (Python):
from math import ceil
N, K = map(int, input().split())
A = list(map(int, input().split()))
F = list(map(int, input().split()))
A.sort()
F.sort(reverse=True)

lo, hi = 0, max(a*f for (a, f) in zip(A,F))
while lo < hi:
    mid = (lo + hi)//2
    rsd = K
    possible = True
    for a, f in zip(A,F):
        rsd -= ceil(max(a*f-mid, 0)/f)
        if rsd < 0:
            possible = False
            break
    if possible:
        hi = mid
    else:
        lo = mid+1

print(lo)

Solution (Python):
import numpy as np

N, K = map(int, input().split())
A_lis = list(map(int, input().split()))
F_lis = list(map(int, input().split()))
A_lis = np.sort(A_lis)[::-1]
F_lis = np.sort(F_lis)

if A_lis.sum() <= K:
    print(0)
    exit()
if K == 0:
    print((A_lis * F_lis).max())

high = (A_lis * F_lis).max()
low = 0

while high > low + 1:
    mid = (high + low) // 2
    if (A_lis - np.minimum(A_lis, (mid // F_lis))).sum() <= K: 
        high = mid
    else:
        low = mid
print(high)

Solution (Python):


import sys


def get_an(s,t):
  
  return s//t


N,K = map(int, input().split())
An = list(map(int, sys.stdin.readline().rstrip().split()))
An = sorted(An)
Fn = list(map(int, sys.stdin.readline().rstrip().split()))
Fn = sorted(Fn,reverse=True)
MX = An[0]*Fn[0]
for i in range(N):
  MX = max(MX,An[i]*Fn[i])

def check(ret):
  k = K
  for i in range(N):
    if An[i]*Fn[i] <= ret:
      continue
    else:
     k -= An[i]-get_an(ret,Fn[i])
  if k < 0:
    return False
  else:
    return True

l,r = 0,MX
while r-l > 1:
  c = (l+r)//2
  if check(c):
    r = c
  else:
    l = c
if check(l):
  print(l)
else:
  print(r)

Solution (Python):
import math
N,K=[int(s) for s in input().split()]
ls1=[int(s) for s in input().split()]
ls2=[int(s) for s in input().split()]
ls1.sort()
ls2.sort()
M=max([ls1[i]*ls2[N-1-i] for i in range(N)])


def pos(a):
  s=0
  for i in range(N):
    s+=max([0,math.ceil(ls1[i]-a/ls2[N-1-i])])
  if s>K:
    return 0
  else:
    return 1
x=0
y=M//2
z=M
while z-x>1:
  if pos(y)==1:
    z=y
  else:
    x=y
  y=(x+z)//2

if pos(y)==1:
  print(y)
else:
  print(z)

Solution (Python):
import sys
sys.setrecursionlimit(10000000)
import heapq
import math
 
def main():
    N, K = map(int, input().split())
    A = [int(c) for c in input().split()]
    F = [int(c) for c in input().split()]
    
    A.sort()
    F.sort(reverse=True)
 
    num = 0
    sum_ = []
    for i in range(N):
      sum_.append(A[i] * F[i])
    left = 0
    right = 10 ** 12
    while(num < 90):
        number = 0
        mid = (left + right) // 2
        
        for i in range(len(A)):
            if sum_[i] <= mid:
                continue
            else:
                number += math.ceil((sum_[i] - mid) / F[i])
            
        if number > K:
            
            left = mid + 1
        else:
            right = mid
        num += 1
    print(mid)
                
        
 
 
 
if __name__ == '__main__':
    main()

Solution (Python):

import sys
input = sys.stdin.readline


N,K = map(int,input().split())
*A, = map(int,input().split())
*F, = map(int,input().split())

F.sort(reverse=True)
A.sort()

def check(n):
    if n==-1: return False
    cost = 0
    for a,f in zip(A,F):
        if a*f>n:
            cost += a - n//f
    return cost <= K

l = -1
r = 10**13
while l+1<r:
    i = (l+r)//2
    if check(i):
        r = i
    else:
        l = i

print(r)

Solution (Python):
import numpy as np

N, K = map(int, input().split())
A = np.array(input().split(), np.int64)
F = np.array(input().split(), np.int64)
A.sort()
F.sort()
F = F[::-1]
dig = A.sum()


def judge(x):
    return dig - np.minimum(A, x // F).sum() <= K


l = -1
r = 10 ** 18 + 1

while l + 1 < r:
    test = (l + r) // 2
    if judge(test):
        r = test
    else:
        l = test

print(r)

Solution (Python):
N, K = map(int, input().split())
A = sorted([int(i) for i in input().split()])
F = sorted([int(i) for i in input().split()], reverse=True)

if sum(A) <= K:
    print(0)
    exit()
else:
    OK = 10**12
    NG = 0

    while OK-NG > 1:
        mid = (OK+NG)//2
        cnt = 0

        for i, a in enumerate(A):
            cnt += max(0, a-mid//F[i])
        if cnt <= K:
            OK = mid
        else:
            NG = mid

print(OK)

Solution (Python):
import sys
input = sys.stdin.readline

def main():
    N, K = map(int, input().split())
    A = list(map(int, input().split()))
    F = list(map(int, input().split()))

    F.sort(reverse=True)
    A.sort()
    l = -1
    r = 0
    for i in range(N):
        if A[i]*F[i] > r:
            r = A[i]*F[i]
    r += 1
    while r-l > 1:
        m = (r+l)//2
        q = []
        cost = 0
        for i in range(N):
            if F[i]*A[i] > m:
                cost += (F[i]*A[i]-m)//F[i]
                if (F[i]*A[i]-m)%F[i] != 0:
                    cost += 1
        if cost <= K:
            r = m
        else:
            l = m

    print(r)


if __name__ == "__main__":
    main()

Solution (Python):
from heapq import heappop, heappush
N, K = map(int, input().split())
A = list(map(int, input().split()))
F = list(map(int, input().split()))

def ok(x):
    cnt = 0
    for i in range(N):
        current = A[i] * F[i]
        if current > x:
            cnt += -(-(current - x) // F[i])
            
    return cnt <= K

A.sort()
F.sort(reverse=True)
lb = 0
ub = 10 ** 12 + 1

while ub - lb > 1:
    mid = (lb + ub) // 2
    
    if ok(mid):
        ub = mid
    else:
        lb = mid
        
if sum(A) <= K:
    print(0)
else:
    print(ub)

Solution (Python):
import sys

def solve():
    input = sys.stdin.readline
    N, K = map(int, input().split())
    A = [int(a) for a in input().split()]
    F = [int(f) for f in input().split()]
    A.sort(reverse = True)
    F.sort()
    low, high = -1, 10 ** 12 + 1
    while high - low > 1:
        mid = (low + high) // 2
        count = 0
        for i in range(N):
            if A[i] * F[i] > mid: count += A[i] - (mid // F[i])
        if count > K: low = mid
        else: high = mid
    print(high)

    return 0

if __name__ == "__main__":
    solve()

Solution (Python):
import sys
input=sys.stdin.readline
n,k=map(int,input().split())
a=list(map(int,input().split()))
a=sorted(a)
f=list(map(int,input().split()))
f=sorted(f,reverse=True)

s=sum(a)
if k>=s:
    print(0)
    exit()

def is_ok(b):
    m=0
    for p,q in zip(a,f):
        if p>b//q:
            m+=p-(b//q)
            if m>k:
                return False
    return True

ok=10**12+1
ng=0
while ok-ng>1:
    m=(ok+ng)//2
    if is_ok(m):
        ok=m
    else:
        ng=m

print(ok)

Solution (Python):
import numpy as np
N,K=map(int,input().split())
A=np.array(sorted(list(map(int,input().split()))))
F=np.array(sorted(list(map(int,input().split())), reverse=True))
s=A.sum()
l=-1
r=10**12+2
while l+1<r:
    m=(l+r)//2
    if s-np.minimum(A,m//F).sum()<=K:
        r=m
    else:
        l=m
print(r)

Solution (Python):
n,k = map(int,input().split())
a_ls = list(map(int,input().split()))
f_ls = list(map(int,input().split()))

a_ls.sort(reverse=True)
f_ls.sort()

l=-1
r=a_ls[0] * f_ls[-1]
while(l+1<r):
    c=(l+r)//2
    total = 0
    for i in range(n):
        a = max(a_ls[i] * f_ls[i] - c, 0)
        b = f_ls[i]
        total += (a+b-1)//b
    if total > k:
        l=c
    else:
        r=c
print(r)

Solution (Python):

import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
from operator import add, mul, sub

sys.setrecursionlimit(100000)
input = sys.stdin.readline
INF = 2**62-1

def read_int():
    return int(input())


def read_int_n():
    return list(map(int, input().split()))


def read_float():
    return float(input())


def read_float_n():
    return list(map(float, input().split()))


def read_str():
    return input().strip()


def read_str_n():
    return list(map(str, input().split()))


def error_print(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.time()
        ret = f(*args, **kwargs)
        e = time.time()

        error_print(e - s, 'sec')
        return ret

    return wrap


class Bisect:
    def __init__(self, func):
        self.__func = func

    def bisect_left(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if self.__func(mid) < x:
                lo = mid+1
            else:
                hi = mid
        return lo

    def bisect_right(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if x < self.__func(mid):
                hi = mid
            else:
                lo = mid+1
        return lo

@mt
def slv(N, K, A, F):
    A.sort(reverse=True)
    F.sort()

    def possible(c):
        k = K
        for a, f in zip(A, F):
            d = c//f
            if d - a < 0:
                k += d - a
        if k >= 0:
            return 1
        return 0
    
    b = Bisect(possible)
    return b.bisect_left(1, 0, 10**18)


def main():
    N, K = read_int_n()
    A = read_int_n()
    F = read_int_n()
    print(slv(N, K, A, F))


if __name__ == '__main__':
    main()

Solution (Python):
N, K = map(int, input().split())
A = sorted([int(i) for i in input().split()])
F = sorted([int(i) for i in input().split()], reverse=True)

if sum(A) <= K:
    print(0)
    exit()
else:
    OK = 10**12
    NG = -1

    while OK-NG > 1:
        mid = (OK+NG)//2
        cnt = 0

        for i, a in enumerate(A):
            cnt += max(0, a-mid//F[i])
        if cnt <= K:
            OK = mid
        else:
            NG = mid

print(OK)

Solution (Python):
n,k=map(int,input().split())
A=[int(i) for i in input().split()]
F=[int(i) for i in input().split()]
A.sort()
F.sort()

def chk(x):
  ct=0
  for i in range(n):
    a,f=A[i],F[-i-1]
    ct+=max(0,a-x//f)
  if ct<=k:
    return True
  else:
    return False


l,r=0,A[-1]*F[-1]
while r-l>1:
  m=(l+r)//2
  if chk(m):
    r=m
  else:
    l=m

if chk(l):
  print(l)
else:
  print(r)

Solution (Python):
import numpy as np
def solve(n, k, aaa, fff):
    aaa = np.sort(aaa)
    fff = np.sort(fff)[::-1]
    l = 0
    r = 10 ** 12
    while l <= r:
        m = (l + r) // 2
        req = np.clip(aaa - m // fff, 0, None).sum()
        if req > k:
            l = m + 1
        else:
            r = m - 1
    return l
n, k = list(map(int, input().split()))
aaa = np.array(list(map(int, input().split())), dtype=np.int64)
fff = np.array(list(map(int, input().split())), dtype=np.int64)
print(solve(n, k, aaa, fff))

Solution (Python):
n,k = map(int,input().split())
a = list(map(int,input().split()))
b = list(map(int,input().split()))
a.sort()
b.sort(reverse=True)


big = 44
stand = 2 ** big
width = 2 ** (big-1)
if sum(a) <= k:
  print(0)
else:
  while True:
    tmp = []
    for i in range(n):
       tmp.append(max(0,a[i]-stand//b[i]))
    if width == 0:
      if sum(tmp) <= k:
        print(stand)
      else:
        print(stand+1)
      break
    if sum(tmp) <= k:
      stand -= width
      width //= 2
    else:
      stand += width
      width //= 2

Solution (Python):
import numpy as np
N, K = map(int, input().split())
A = np.array(list(map(int, input().split())))
F = np.array(list(map(int, input().split())))
A = np.sort(A)[::-1]
F = np.sort(F)

if A.sum() <= K:
    print(0)
    exit()
if K == 0:
    print((A * F).max())
up = (A * F).max() 
low = 0 
while up > low + 1:
    mid = (up + low) // 2
    if (A - np.minimum(A, (mid // F))).sum() <= K: 
        up = mid
    else:
        low = mid
print(up)

Solution (Python):

import sys, math


def solve(N: int, K: int, A: "List[int]", F: "List[int]"):
    A = sorted(A)
    F = sorted(F, reverse=True)
    B = [a*f for a, f in zip(A, F)]
    b = max(B)
    left = -1
    right = b

    def ok(mid):
        r = 0
        for i in range(N):
            a, f = A[i], F[i]
            r += max(0, a - mid//f)
        if r > K:
            return True
        else:
            return False

    while right - left > 1:
        mid = (right + left) // 2
        if ok(mid):
            left = mid
        else:
            right = mid
    print(right)
    return



def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  
    K = int(next(tokens))  
    A = [int(next(tokens)) for _ in range(N)]  
    F = [int(next(tokens)) for _ in range(N)]  
    solve(N, K, A, F)

if __name__ == '__main__':
    main()

Solution (Python):
N, K = map(int, input().split())
A = [int(i) for i in input().split()]
F = [int(i) for i in input().split()]

A.sort(reverse=True)
F.sort()

ng = -1
ok = 10**12
while ok - ng > 1 :
    mid = (ok + ng) // 2
    k = 0
    for i in range(N) :
        k += max(0, A[i] - mid // F[i])
    if k <= K :
        ok = mid
    else :
        ng = mid
print(ok)

Solution (Python):
N, K = map(int, input().split())
A = list(map(int, input().split()))
F = list(map(int, input().split()))
A.sort()
F.sort()
F.reverse()


M = [0] * N
for i in range(N):
    M[i] = A[i] * F[i]

def Below(X, K):
    for i in range(N):
        if A[i]*F[i] <= X:
            continue
        else:
            cost = X // F[i]
            K -= (A[i] - cost)
    if K >= 0:
        return True
    else:
        return False

left = 0
right = max(M)
while left != right:
    mid = (left + right) // 2
    
    if Below(mid, K):
        right = mid
    else:
        left = mid + 1

print(left)

Solution (Python):
import sys

input = sys.stdin.readline


def read_i():
    return list(map(int, input().split()))


def check(m, k, vs):
    s = 0
    for x, y, v in vs:
        if v >= m:
            s += (v - m + y - 1) // y
    return s <= k


n, k = read_i()
ls0 = sorted(read_i())
ls1 = sorted(read_i(), reverse=True)
if sum(ls0) <= k:
    print(0)
    exit()

vs = [(x, y, x * y) for x, y in zip(ls0, ls1)]

lo = 0
hi = sum(v for _, _, v in vs)
while hi - lo > 1:
    mid = (lo + hi) // 2
    if check(mid, k, vs):
        hi = mid
    else:
        lo = mid
print(hi)

Solution (Python):

N,K = map(int,input().split())
A = list(map(int,input().split()))
F = list(map(int,input().split()))

import copy
A.sort(reverse = True)
DA = copy.copy(A)
F.sort()

import sys
if (sum(A) <= K):
    print(0)
    sys.exit()

values = [0]*N
for i in range(N):
    values[i] = A[i]*F[i]

def judge(val):
    cnt = 0
    for i in range(N):
        if (values[i] > val):
            cnt += A[i]-val//F[i]
    
    return cnt<=K

s = 0
e = max(A)*max(F)
while (s<e):
    c = (s+e)//2
    if judge(c):
        e = c-1
        
    else:
        s = c+1

while(judge(c)):
    c-=1
while (not(judge(c))):
    c+=1
print(c)

Solution (Python):
n,k=map(int,input().split())
a=list(map(int,input().split()))
f=list(map(int,input().split()))
a.sort()
f.sort(reverse=1)
su=ok=ng=0
for i in range(n):
  ok=max(ok,a[i]*f[i])
  su+=a[i]
if su<=k:print(0);exit()
while ng+1!=ok:
  mid=(ok+ng)//2
  b=[mid//i for i in f]
  b.sort()
  h=0
  for i in range(n):h+=max(0,a[i]-b[i])
  if h<=k:ok=mid
  else:ng=mid
print(ok)

Solution (Python):
import math
N, K = map(int, input().split())
As = list(map(int, input().split()))
Fs = list(map(int, input().split()))

As.sort()
As.reverse()
Fs.sort()
arr = []
M = 0
for a, f in zip(As, Fs):
    af = a*f
    arr.append((af, a, f))
    M = af if af > M else M

f = -1
t = M
while f + 1 < t:
    m = f + math.ceil((t-f) / 2)
    k = K
    for AF, A, F in arr:
        d = A - m // F
        d = d if d >= 0 else 0
        if d > k:
            f = m
            break
        k -= d
    else:
        t = m

print(t)

Solution (Python):
import sys
input=sys.stdin.readline  
 
def main():
    n,k=map(int,input().split())
    a=sorted(map(int,input().split()))
    b=sorted(map(int,input().split()),reverse=1)
    
    ok=max(a)*max(b)
    ng=-1
    
    def check(a,b,mid,k):
        if sum(a[i]-mid//b[i]for i in range(n) if a[i]*b[i]>mid)<=k:
            return 1
        else:
            return 0
            
    while abs(ok-ng)>1:
        mid=(ok+ng)//2
        if check(a,b,mid,k):
            ok=mid
        else:
            ng=mid
    print(ok)

if __name__ == '__main__':
    main()

Solution (Python):
import heapq
n,k=map(int,input().split())
a=list(map(int,input().split()))
f=list(map(int,input().split()))
a.sort()
f.sort()
f.reverse()
l=0;r=max(a)*max(f)
sum=sum(a)
while abs(l-r)>1:
  x=(l+r)//2
  ct=0
  for i in range(n):
    ct+=max(a[i]-(x//f[i]),0)
  if ct<=k:
    r=x
  else:
    l=x+1
x=l
ct=0
for i in range(n):
  ct+=max(a[i]-(x//f[i]),0)
if ct<=k:
  print(l)
else:
  print(r)