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 can(X):
    training = 0
    for i in range(N):
        training += max(math.ceil(A[i] - X / F[i]), 0)
    return training <= K

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

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

a = 0
b = max(A) * max(F) * N
c = 0

while (b - a) >= 1:
    c = (a + b) / 2
    if can(c):
        b = c
    else:
        a = c

res = math.floor(c)

if can(res):
    print(res)
else:
    print(res + 1)

Solution (Python):

import numpy as np
def resolve():
    
    
    def check(X):
        
        a = X // F
        diff = np.maximum(A - a, 0)
        cnt = np.sum(diff)
        return cnt <= K

    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]

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

    print(ok)


if __name__ == "__main__":
    resolve()

Solution (Python):

def resolve():
    
    
    def check(X):
        cnt = 0
        for i in range(N):
            a = X // F[i]
            if a < A[i]:  
                cnt += A[i] - a
        return cnt <= K

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

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

    print(ok)


if __name__ == "__main__":
    resolve()

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 = True)
af = [a[i]*f[i] for i in range(n)]

def check(x):
  r = 0
  for i in range(n):
    r += (max(0,(af[i]-x))+f[i]-1)//f[i]
  
  if r<=k:
    return True
  else:
    return False
ok = 10**12+1
ng = -1
while ok-ng>1:
  mid = (ok + ng)//2
  if check(mid):
    ok = mid
  else:
    ng = mid
print(ok)

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

ng = -1
ok = 0
for i in range(N):
  ok = max(A[i]*F[i], ok)

def is_ok(arg):
  cnt = 0
  for i in range(N):
    cnt += max(A[i] - arg//F[i], 0)
  return cnt <= K

def m_bisect(ng, ok):
  while (abs(ok - ng) > 1):
    mid = (ok + ng) // 2
    if is_ok(mid):
      ok = mid
    else:
      ng = mid
  return ok

print(m_bisect(ng, ok))

Solution (Python):
import math
N, K = map(int, input().split())
A = sorted([int(i) for i in input().split()], reverse=True)
F = sorted([int(i) for i in input().split()])
OK = 10**12
NG = -1

while OK-NG > 1:
    mid = (OK+NG)//2
    cnt = 0
    for a, f in zip(A, F):
        if a*f > mid:
            cnt += math.ceil((a*f-mid)/f)
    if cnt <= K:
        OK = mid
    else:
        NG = mid
print(OK)

Solution (Python):
from sys import stdin
import sys
import math
from functools import reduce
import functools
import itertools
from collections import deque,Counter,defaultdict
from operator import mul
import copy


import heapq
sys.setrecursionlimit(10**6)

INF = 10**18
import bisect
import statistics
mod = 10**9+7


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

ng = -1
ok = 10**12 + 1

def is_ok(m):
    FF = [m//f for f in F]
    p = 0
    for i in range(len(A)):
        p += max(0, A[i] - FF[i])
    if K >= p:
        return True
    else:
        return False

while (abs(ok-ng)>1):
    mid = (ng + ok) // 2
    if is_ok(mid):
        ok = mid
    else:
        ng = mid

print(ok)

Solution (Python):
n,k=map(int,input().split())
*a,= map(int,input().split())
*f,= map(int,input().split())
a=sorted(a)
f=sorted(f, reverse=True)

def is_ok(arg):
    cnt=0
    for i in range(n):
        cnt+=max(a[i]-arg//f[i], 0)
    return cnt<=k

def meguru_bisect(ng, ok):
    while (abs(ok - ng) > 1):
        mid = (ok + ng) // 2
        if is_ok(mid):
            ok = mid
        else:
            ng = mid
    return ok

print(meguru_bisect(-1, 10**12))

Solution (Python):
import math
n, k = [int(i) for i in input().split()]
a = [int(i) for i in input().split()]
f = [int(i) for i in input().split()]

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

af = [[a[i]*f[i], a[i], f[i]] for i in range(n)]
af.sort(reverse=True)

def check(mid):
    count = 0
    for i in range(n):
        num = math.ceil((af[i][0] - mid) / af[i][2])
        if num > af[i][1]:
            return False
        else:
            count += num
            if count > k:
                return False
    else:
        return True


def binary_search():
    ng = -1 
    ok = 10**13 
    while (ok - ng > 1):
        mid = (ng + ok) // 2
        if check(mid) == True:
            ok = mid
        else:
            ng = mid
    return ok
print(binary_search())

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=True)
AF = [A[i]*F[i] for i in range(N)]

l = -1
r = max(AF)

while r-l > 1:
    x = (l+r)//2
    k =0
    
    for i in range(N):
        if AF[i]<=x:
            continue
        else:
            k += A[i]-x//F[i]
    if k <= K:
        r = x
    else:
        l=x

print(r)

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=True)

def check(s):
  ret=0
  for i,j in zip(a,f):
    ret+=max(0,i-s//j)
  return ret<=k

ok=10**12+1
ng=-1
while ok-ng>1:
  mid=(ok+ng)//2
  if check(mid):
    ok=mid
  else:
    ng=mid
print(ok)

Solution (Python):
n,k=map(int,input().split())
abilities=sorted(list(map(int,input().split())))
foods=sorted(list(map(int,input().split())),reverse=True)

if sum(abilities)<=k:
  print(0)
  exit()
  
def check(score):
  ret=0
  for a,f in zip(abilities,foods):
    ret+=max(0,(a*f-score+f-1)//f)
  return ret<=k

ok=10**12+1
ng=0
for _ in range(50):
  mid=(ok+ng)//2
  if check(mid):
    ok=mid
  else:
    ng=mid
print(ok)

Solution (Python):


import math

import itertools
from collections import deque
from collections import Counter
import heapq


import bisect
n,k=map(int,input().split())
a=list(map(int,input().split()))
f=list(map(int,input().split()))
a.sort()
f.sort(reverse=True)
l=-1
r=a[-1]*f[0]

while r>l+1:
    cnt=0
    mid=(l+r)//2
    for i in range(n):
        cost=a[i]*f[i]
        if cost>mid:
            cnt+=a[i]-math.floor(mid/f[i])
    if cnt<=k:
        r=mid
    else:
        l=mid
print(r)

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=True)
l,r = 0,10**12+1
while l <r:
    mid = (l+r)//2
    cnt = 0
    for a,f in zip(A,F):
        cnt += max(0,a-mid//f)
    if cnt <=k:
        r = mid
    else:
        l = mid+1
print(l)

Solution (Python):

from collections import defaultdict, deque, Counter, OrderedDict
from bisect import bisect_left, bisect_right
from functools import reduce, lru_cache
from heapq import heappush, heappop, heapify

import itertools
import math, fractions
import sys, copy

def L(): return sys.stdin.readline().split()
def I(): return int(sys.stdin.readline().rstrip())
def SL(): return list(sys.stdin.readline().rstrip())
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def LI1(): return [int(x) - 1 for x in sys.stdin.readline().split()]
def LS(): return [list(x) for x in sys.stdin.readline().split()]
def IR(n): return [I() for _ in range(n)]
def LIR(n): return [LI() for _ in range(n)]
def LIR1(n): return [LI1() for _ in range(n)]
def SR(n): return [SL() for _ in range(n)]
def LSR(n): return [LS() for _ in range(n)]
def LR(n): return [L() for _ in range(n)]

def perm(n, r): return math.factorial(n) // math.factorial(r)
def comb(n, r): return math.factorial(n) // (math.factorial(r) * math.factorial(n-r))

def make_list(n, *args, default=0): return [make_table(*args, default=default) for _ in range(n)] if len(args) > 0 else [default for _ in range(n)]

alphabets = "abcdefghijklmnopqrstuvwxyz"
ALPHABETS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

sys.setrecursionlimit(1000000)
dire = [[1, 0], [0, 1], [-1, 0], [0, -1]]
dire8 = [[1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1]]
MOD = 1000000007
INF = float("inf")

def main():
    N, K = LI()
    A = sorted(LI())
    F = sorted(LI(), reverse=True)

    left = -1
    right = (10 ** 12) + 1

    while right - left > 1:
        tmp = 0
        mid = (right + left) // 2
        
        for ai, fi in zip(A, F):
            xi = mid // fi
            tmp += max(0, ai - xi)
            
        if tmp <= K:
            right = mid
        else:
            left = mid

    print(right)

if __name__ == '__main__':
    main()

Solution (Python):
import numpy as np


def is_good(mid, key):
    x = A - mid // F
    return x[x > 0].sum() <= key


def binary_search(key):
    bad, good = -1, 10 ** 18
    while good - bad > 1:
        mid = (bad + good) // 2
        if is_good(mid, key):
            good = mid
        else:
            bad = mid
    return good


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

Solution (Python):
n, k = map(int, input().split())
a = map(int, input().split())
f = map(int, input().split())
a = sorted(a)
f = sorted(f)[::-1]


def c(x):
    
    res = 0
    for O, K in zip(a, f):
        d = max(0, O * K - x)
        res += (d + K - 1) // K
    return res <= k


l = -1
r = 1 << 60
while r - l > 1:
    mid = (l + r) >> 1
    if c(mid):
        r = mid
    else:
        l = mid
print(r)

Solution (Python):
def is_good(mid, key):
    ret = 0
    for i in range(N):
        ret += max(0, A[i] - mid // F[i])
    return ret <= key


def binary_search(key):
    bad, good = -1, 10 ** 18
    while good - bad > 1:
        mid = (bad + good) // 2
        if is_good(mid, key):
            good = mid
        else:
            bad = mid
    return good


N, K = map(int, input().split())
A = sorted(map(int, input().split()))
F = sorted(map(int, input().split()), reverse=True)
print(binary_search(K))

Solution (Python):

import sys
def main(N, K, A, F):
    A.sort()
    F.sort(reverse=True)

    def f(x):
        sy = 0
        for a, f in zip(A, F):
            m = a * f
            if m > x:
                sy += (m - x + f - 1) // f
        return sy

    under = -1
    hi = 10**12 + 1
    while hi - under > 1:
        m = (hi + under) // 2
        if f(m) <= K: hi = m
        else: under = m
    print(hi)

if __name__ == '__main__':
    input = sys.stdin.readline
    N, K = map(int, input().split())
    *A, = map(int, input().split())
    *F, = map(int, input().split())
    main(N, K, A, F)

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=True)

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

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

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

ok, ng = 10**12+1, -1
while abs(ok-ng) > 1:
    mid = (ok+ng)//2
    ok_flag = True
    
    cnt = 0
    for a,f in zip(al,fl):
        v = a*f
        rem = a*f-mid
        cnt += max( (rem-1)//f+1, 0)
    if cnt <= k:
        ok = mid
    else:
    	ng = mid
print(ok)

Solution (Python):
"""
成績をSにできるか？という二分探索をするのがよさそう。
S秒以内に全員が食べ終わった状態でいる必要がある。
S/xをすることで、各メンバーのキャパシティが見えてくる。
あとは「食べ物をどう割り当てるか」だけどこれは貪欲的にキャパシティの小さい順に、食べづらさの小さい食べ物を割り当てればOK。
もし、キャパシティが足りない場合はK回までxを調整して、キャパシティを計算しなおす。
計算量としては、O(log(10**12)N)で間に合う。

"""

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

A.sort(reverse=True)
F.sort()
from math import ceil

def is_ok(S):
    tmpK = K
    for i in range(N):
        f = F[i]
        a = A[i]
        if S//a < f:
            x = ceil(a-S/f)
            tmpK -= x
        if tmpK < 0:
            return False
    return True

def bisearch(high,low):
    while high - low > 1:
        mid = (high+low)//2
        if is_ok(mid):
            high = mid
        else:
            low = mid
    return high

print(bisearch(max(A)*max(F),-1))

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

def main():
    N, K = map(int, input().rstrip().split())
    A = list(map(int, input().rstrip().split()))
    F = list(map(int, input().rstrip().split()))
    A.sort()
    F.sort(reverse=True)
    l = -1
    r = 10 ** 12
    while(r - l > 1):
        c = (l + r) // 2
        s = 0
        for i in range(N):
            d = A[i] - (c // F[i])
            s += max(0, d)
        if s <= K:
            r = c
        else:
            l = c
    print(r)

if __name__ == "__main__":
    main()

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=sorted(A)
F=sorted(F, reverse=True)

left=0
right=10**12+1
ans=float("INF")
while True:
    mid=(left+right)//2

    now=0
    for i in range(N):
        if F[i]*A[i]>mid:
            now+=ceil(((F[i]*A[i])-mid)/F[i])
    
    if now==K:
        ans=min(ans, mid)
        if right==mid:
            break
        right=mid
    elif now>K:
        if left==mid:
            break
        left=mid
    else:
        if right==mid:
            break
        right=mid
        ans=min(ans, mid)

print(ans)

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=True)

la = 10**12+1
sm = -1
while sm+1<la:
    mi = (sm+la)//2
    y=0
    for i in range(N):
        y += max(0, A[i]-(mi//F[i]))
    if y<=K:
        la = mi
    else:
        sm = mi
print(la)

Solution (Python):
import sys

import numba as nb
import numpy as np

input = sys.stdin.readline


@nb.njit("i8(i8,i8[:],i8[:])", cache=True)
def binary_search(K, A, F):
    ng = -1
    ok = 10 ** 18
    while ok - ng > 1:
        mid = (ok + ng) // 2
        need_k = 0
        for a, f in zip(A, F):
            need_k += max(0, a - mid // f)
        if need_k <= K:
            ok = mid
        else:
            ng = mid
    return ok


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

    A = np.sort(A)
    F = np.sort(F)[::-1]

    ans = binary_search(K, A, F)
    print(ans)


if __name__ == "__main__":
    main()

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=True)
lef = -1
rig = 10**13

while rig - lef != 1:
    now = (rig + lef) //2
    cou = 0
    for i in range(n):
        t = now // f[i]
        cou += max(0,a[i]-t)
    if cou <= k:
        rig = now
    elif cou > k:
        lef = now
print(rig)

Solution (Python):
n,k = map(int,input().split())
A = sorted(list(map(int,input().split())))
F = sorted(list(map(int,input().split())))[::-1]
o = []
for a,f in zip(A,F):
    o.append(a*f)
ok = max(o)    
ng = -1

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

Solution (Python):
import sys
from collections import deque
import bisect
import copy
import heapq
import itertools
import math
input = sys.stdin.readline
sys.setrecursionlimit(1000000)
mod = 10 ** 9 + 7

def read_values(): return map(int, input().split())
def read_index(): return map(lambda x: int(x) - 1, input().split())
def read_list(): return list(read_values())
def read_lists(N): return [read_list() for n in range(N)]


def cal(A, F, m):
    res = 0
    for a, f in zip(A, F):
        c = m // f
        res += max(0, a - c)
    return res


def main():
    N, K = read_values()
    A = read_list()
    F = read_list()
    A.sort()
    F.sort(reverse=True)

    l = 0
    r = 10 ** 12
    while l < r:
        m = (l + r) // 2
        if cal(A, F, m) > K:
            l = m + 1
        else:
            r = m
    
    print(r)


if __name__ == "__main__":
    main()

Solution (Python):
import sys

input = sys.stdin.readline

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


def can_eat(t):
    F_time = sorted([t // f for f in F])
    training = 0
    for i in range(N):
        training += max(0, A[i] - F_time[i])
    return training <= K



l, r = -1, 10 ** 12
while r - l > 1:
    m = (r + l) // 2
    if can_eat(m):
        r = m
    else:
        l = m
print(r)

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

A.sort(reverse=True)
F.sort()
wk = 0
for i in range(N):
  wk += A[i] * F[i]


def is_ok(arg):
  
  cnt = 0
  for i in range(N):
    a,f = A[i], F[i]   
    if a*f <= arg:
      continue
    else:
      
      
      cnt += ceil(a-arg/f)
  return cnt <= K

def meguru_bisect(ng, ok):
  '''
    初期値のng,okを受け取り,is_okを満たす最小(最大)のokを返す
    まずis_okを定義すべし
    ng ok は  とり得る最小の値-1 とり得る最大の値+1
    最大最小が逆の場合はよしなにひっくり返す
    '''
  while (abs(ok - ng) > 1):
    mid = (ok + ng) // 2
    if is_ok(mid):
      ok = mid
    else:
      ng = mid
  return ok

ng = -1
ok = 10**12 + 10
ans = meguru_bisect(ng,ok)

print(ans)

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

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

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

def check(x):
  k = 0
  for a,f in zip(A, F):
    k += max(0, a-(x//f))

  return k <= K


ng,ok = 0, 10**18+1
while ok-ng > 1:
  x = (ok+ng)//2
  if check(x):
    ok = x
  else:
    ng = x

print(ok)

Solution (Python):
import sys
n, k = map(int, input().split())
a = list(map(int, input().split()))
f = list(map(int, input().split()))
a.sort()
f.sort(reverse=True)
l, r = -1, 10 ** 12 + 1
while r - l > 1:
    m = (l + r) // 2
    cnt = 0
    for i in range(n):
        cnt += max(0, a[i] - (m // f[i]))
    if cnt <= k:
        r = m
    else:
        l = m
print(r)

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=True)

ub = 10 ** 12 + 10
lb = 0
while ub - lb > 1:
    mid = (ub + lb) // 2
    cnt = 0
    for x, y in zip(A, F):
        res = max(0, x * y - mid)
        cnt += -(-res // y)

    if cnt <= K:
        ub = mid
    else:
        lb = mid

if sum(A) <= K:
    print(0)
else:
    print(ub)

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

def binary_search_int(ok, ng, test):
    """
    :param ok: solve(x) = True を必ず満たす点
    :param ng: solve(x) = False を必ず満たす点
    """
    while abs(ok - ng) > 1:
        mid = (ok + ng) // 2
        if test(mid):
            ok = mid
        else:
            ng = mid
    return ok


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

def max2(x,y):
    return x if x > y else y

def test(x):
    temp = K
    for a, f in zip(A, F):
        temp -= max2((a - x//f), 0)
        if temp < 0:
            return False
    return True

print(binary_search_int(A[-1]**2 + 100, -1,test))

Solution (Python):
import sys
import re
import math
import collections
import decimal
import bisect
import itertools
import fractions
import functools
import copy
import heapq
import decimal
import statistics
import queue



sys.setrecursionlimit(10 ** 9)
INF = 10 ** 16
MOD = 10 ** 9 + 7


ni = lambda: int(sys.stdin.readline())
ns = lambda: map(int, sys.stdin.readline().split())
na = lambda: list(map(int, sys.stdin.readline().split()))




def main():
    worst_score = 10 ** 12

    n, k = ns()
    a = na()
    f = na()
    a.sort()
    f.sort(reverse=True)
    score = [ai * fi for ai, fi in zip(a, f)]

    l = -1
    r = worst_score + 1

    while r - l > 1:
        middle = (l + r) // 2
        tmp_k = k
        for i in range(n):
            tmp = math.ceil((score[i] - middle) / f[i])
            tmp_k -= max(0, tmp)

            if tmp_k < 0:
                break

        if tmp_k >= 0:
            r = middle
        else:
            l = middle
    print(r)

if __name__ == '__main__':
    main()

Solution (Python):
import sys
import re
import math
import collections
import decimal
import bisect
import itertools
import fractions
import functools
import copy
import heapq
import decimal
import statistics
import queue



sys.setrecursionlimit(10 ** 9)
INF = 10 ** 16
MOD = 10 ** 9 + 7


ni = lambda: int(sys.stdin.readline())
ns = lambda: map(int, sys.stdin.readline().split())
na = lambda: list(map(int, sys.stdin.readline().split()))




def main():
    worst_score = 10 ** 12

    n, k = ns()
    a = na()
    f = na()
    a.sort()
    f.sort(reverse=True)
    score = [ai * fi for ai, fi in zip(a, f)]

    l = 0
    r = worst_score

    while True:
        middle = (l + r) // 2

        tmp_k = k
        for i in range(n):
            tmp = (score[i] - middle + f[i] - 1) // f[i]
            tmp_k -= max(0, tmp)

            if tmp_k < 0:
                break

        if r - l == 1:
            print(middle if tmp_k >= 0 else middle + 1)
            exit(0)

        if tmp_k < 0:
            l = middle
        else:
            r = middle





if __name__ == '__main__':
    main()

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=True)

def check(mid):
    cnt = 0
    for i in range(N):
        tmp = mid // F[i]
        cnt += max(A[i] - tmp, 0)
    return cnt <= K

check(2)

l, r = -1, 10**30
while r-l > 1:
    mid = (l+r)//2
    if check(mid):
        r = mid
    else:
        l = mid

print(r)

Solution (Python):
def abc144_e():
    import numpy as np

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

    low = -1
    up = 10**12
    while up - low > 1:
        v = (up + low) // 2
        x = A - v // F
        if x[x > 0].sum() > K:
            low = v
        else:
            up = v
    print(up)

if __name__ == '__main__':
    abc144_e()

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

    low = -1
    up = 10**12
    while up - low > 1:
        v = (up + low) // 2
        tk = K
        for i in range(N):
            tk -= max(0, A[i] - (v // F[i]))
            if tk < 0: break
        if tk < 0:
            low = v
        else:
            up = v
    print(up)

if __name__ == '__main__':
    abc144_e()

Solution (Python):
import sys
input = lambda : sys.stdin.readline().rstrip()
sys.setrecursionlimit(max(1000, 10**9))
write = lambda x: sys.stdout.write(x+"\n")


n,k = list(map(int, input().split()))
a = list(map(int, input().split()))
f = list(map(int, input().split()))
a.sort()
f.sort(reverse=True)
def sub(x):
    val = 0
    for aa,ff in zip(a,f):
        val += max(0, aa - (x//ff))
    return val<=k
if sub(0):
    ans = 0
else:
    l = 0
    r = sum(aa*ff for aa,ff in zip(a,f))
    while l+1<r:
        m = (l+r)//2
        if sub(m):
            r = m
        else:
            l = m
    ans = r
print(ans)

Solution (Python):
def resolve():
    N, K = list(map(int, input().split()))
    A = sorted(list(map(int, input().split())))
    F = sorted(list(map(int, input().split())), reverse=True)
    q = []
    for i in range(N):
        q.append((A[i]*F[i], A[i], F[i]))

    def isok(time):
        total = 0
        for t, a, f in q:
            acc = time // f
            if acc < a:
                total += a - acc
        return True if total <= K else False

    left = -1
    right = A[-1]*F[0]
    while (right - left > 1):
        mid = left + (right - left) // 2
        if isok(mid):
            right = mid
        else:
            left = mid
    print(right)

    
if __name__ == "__main__":
    resolve()

Solution (Python):

import sys
sys.setrecursionlimit(10**6)
write = sys.stdout.write
dbg = lambda *something : print(*something) if DEBUG else 0
DEBUG = False
def main(given = sys.stdin.readline):
    from math import floor
    input = lambda : given().rstrip()
    LMIIS = lambda : list(map(int,input().split()))
    II = lambda : int(input())
    XLMIIS = lambda x : [LMIIS() for _ in range(x)]

    N,K = LMIIS()
    A = LMIIS()
    F = LMIIS()


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


    def f(x):
        sum_diff = 0
        for a,f in zip(A,F):
            if a*f-x > 0:
                sum_diff += a-x//f
        return True if sum_diff <= K else False
    l = -1
    r = 10**13
    while r-l>1:

        m = (l+r)//2
        if f(m):
            r = m
        else:
            l = m
    print(r)











if __name__ == '__main__':
    main()

Solution (Python):
import numpy as np

n, k = map(int,input().split()) 
a = list(map(int, input().split()))
f = list(map(int, input().split()))

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

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

a = np.array(a)
f = np.array(f)

lb = -1
ub = a[0]*f[-1]

while ub - lb > 1:
    x = (lb+ub)//2
    cx = np.full(n, x)
    ck = a - x//f
    ck = np.where(ck < 0, 0, ck)
    ck_sum = ck.sum()
    if ck_sum > k:
        lb = x
    else:
        ub = x
print(ub)

Solution (Python):
import sys
import math
from collections import deque

sys.setrecursionlimit(1000000)
MOD = 10 ** 9 + 7
input = lambda: sys.stdin.readline().strip()
NI = lambda: int(input())
NMI = lambda: map(int, input().split())
NLI = lambda: list(NMI())
SI = lambda: input()


def make_grid(h, w, num): return [[int(num)] * w for _ in range(h)]


def main():
    N, K = NMI()
    A = NLI()
    F = NLI()
    A.sort()
    F.sort(reverse=True)
    ok = 10**13
    ng = 0
    for i in range(100):
        mid = (ok+ng) // 2
        limits = [mid//f for f in F]
        ks = [max(a-l, 0) for a, l in zip(A, limits)]
        if sum(ks) <= K:
            ok = mid
        else:
            ng = mid

    print(ok)


if __name__ == "__main__":
    main()

Solution (Python):
n,k=map(int,input().split())
a=sorted(list(map(int,input().split())))

f=sorted(list(map(int,input().split())),reverse=True)
l,r=0,10**12
def cal(x):
    global n,f,a,k
    ret=0
    for i in range(n):
        ret+=max(0,a[i]-(x//f[i]))
    
    return ret
while l+1<r:
    x=l+(r-l)//2
    if cal(x)<=k:
        r=x
    else:
        l=x
if cal(l)<=k:
    print(l)
else:
    print(r)