Schedule Management (Codeforces 1701C)
Tags: Greedy, two pointers

There are $$$n$$$ workers and $$$m$$$ tasks. The workers are numbered from $$$1$$$ to $$$n$$$. Each task $$$i$$$ has a value $$$a_i$$$ — the index of worker who is proficient in this task.Every task should have a worker assigned to it. If a worker is proficient in the task, they complete it in $$$1$$$ hour. Otherwise, it takes them $$$2$$$ hours.The workers work in parallel, independently of each other. Each worker can only work on one task at once.Assign the workers to all tasks in such a way that the tasks are completed as early as possible. The work starts at time $$$0$$$. What's the minimum time all tasks can be completed by?

Input: The first line contains a single integer $$$t$$$ ($$$1 \le t \le 10^4$$$) — the number of testcases.The first line of each testcase contains two integers $$$n$$$ and $$$m$$$ ($$$1 \le n \le m \le 2 \cdot 10^5$$$) — the number of workers and the number of tasks.The second line contains $$$m$$$ integers $$$a_1, a_2, \dots, a_m$$$ ($$$1 \le a_i \le n$$$) — the index of the worker proficient in the $$$i$$$-th task.The sum of $$$m$$$ over all testcases doesn't exceed $$$2 \cdot 10^5$$$.

Output: For each testcase, print a single integer — the minimum time all tasks can be completed by.

Note: In the first testcase, the first worker works on tasks $$$1$$$ and $$$3$$$, and the second worker works on tasks $$$2$$$ and $$$4$$$. Since they both are proficient in the corresponding tasks, they take $$$1$$$ hour on each. Both of them complete $$$2$$$ tasks in $$$2$$$ hours. Thus, all tasks are completed by $$$2$$$ hours.In the second testcase, it's optimal to assign the first worker to tasks $$$1, 2$$$ and $$$3$$$ and the second worker to task $$$4$$$. The first worker spends $$$3$$$ hours, the second worker spends $$$2$$$ hours (since they are not proficient in the taken task).In the third example, each worker can be assigned to the task they are proficient at. Thus, each of them complete their task in $$$1$$$ hour.

Sample Inputs:
4
2 4
1 2 1 2
2 4
1 1 1 1
5 5
5 1 3 2 4
1 1
1

Sample Outputs:
2
3
1
1

Solution (Python):
t = int(input())
for _ in range(t):
    (n, m) = map(int, input().split())
    a = list(map(int, input().split()))
    b = [0] * n
    for i in range(m):
        b[a[i] - 1] += 1
    x = sum(b) // n - 1
    cw = 1
    while cw > 0:
        x += 1
        cw = 0
        for i in range(n):
            if b[i] > x:
                cw += b[i] - x
            elif b[i] < x:
                cc = (x - b[i]) // 2
                cw -= cc
    print(x)

Solution (Python):
def moze(v, r, n):
    s = 0
    for i in range(n):
        if r[i] - v < 0:
            s += (-r[i] + v) // 2
        else:
            s -= r[i] - v
    if s >= 0:
        return True
    return False

def nadji(r, n, m):
    l = (m - 1) // n + 1
    right = 2 * l
    iz = -1
    while l <= right:
        sredina = (l + right) // 2
        if moze(sredina, r, n):
            right = sredina - 1
            iz = sredina
            continue
        else:
            l = sredina + 1
    return iz

def resi():
    (n, m) = map(int, input().split())
    a = list(map(int, input().split()))
    r = [0] * n
    for i in range(m):
        r[a[i] - 1] += 1
    print(nadji(r, n, m))
for _ in range(int(input())):
    resi()

Solution (Python):
import sys
import threading
from random import randint
import os
from io import BytesIO, IOBase
from collections import defaultdict, Counter, deque
from math import inf, sqrt, floor
from functools import lru_cache
from heapq import heappop, heappush, heapify
import math
from bisect import bisect_left, bisect_right
nextInts = lambda : list(map(int, input().split()))
nextInt = lambda : int(input())
Mod = 10 ** 9 + 7

def solution():
    (n, m) = nextInts()
    arr = nextInts()
    cnt = [0] * n
    for val in arr:
        cnt[val - 1] += 1

    def possible(m):
        tasks = 0
        for a in cnt:
            tasks += min(a, m) + (m - min(a, m)) // 2
        return tasks >= len(arr)
    left = 0
    right = (m // n + 1) * 2
    best = right
    while left <= right:
        mid = (left + right) // 2
        if possible(mid):
            right = mid - 1
            best = mid
        else:
            left = mid + 1
    return print(best)

def main():
    t = 1
    t = int(input())
    for _ in range(t):
        solution()
main()