Topics
The key challenge in this problem is to figure out, for each , the maximum number of times (let’s denote it by ) we can pick exactly distinct cards before running out of valid options.
Idea
Reformulating the Problem
- We have distinct integers overall, and for each distinct integer , we know its frequency
- We want to form disjoint groups, each of size , where each group has distinct integers
The distinctness requirement implies that if we want to form such groups, each integer can contribute at most times overall (because you cannot use the same integer more than once in the same group, but you can reuse it in different groups).
Hence, the feasibility condition for a given is:
If this sum is large enough, we can form groups each of size .
Binary Search Over
To find the maximum valid , we can binary-search over possible values of . Let’s denote:
- the sorted frequencies
- A prefix sum array where =
We check feasibility with:
Instead of computing the sum of naively, we note:
- All contribute exactly
- All contribute exactly
Sort . If is the smallest index such that , then
Using prefix sums and a binary search ( in the code) on the frequencies, we can compute this in . Doing that for each up to is acceptable given the constraints.
Edge Cases
- : We can take every card on its own, so the answer is simply the sum of all frequencies
- : Impossible to form a group of size if there aren’t distinct integers
Complexity
- Building the frequency array and prefix sums:
- For each , we do a binary search in
- Overall, for all from 1 to
Code
import sys
import bisect
from collections import Counter
def max_partitions(items_dict, k, prefix_sums, counts):
# Handle edge cases
if k <= 0 or k > len(items_dict):
return 0
# Special case for k=1
if k == 1:
return sum(items_dict.values())
n = len(items_dict)
def can_form_partitions(p):
idx = bisect.bisect_right(counts, p)
available_items = p * (n - idx) + prefix_sums[idx]
return available_items >= p * k
# Binary search for the maximum valid number of partitions
left, right = 0, prefix_sums[n] // k
result = 0
while left <= right:
mid = (left + right) // 2
if can_form_partitions(mid):
result = mid
left = mid + 1
else:
right = mid - 1
return result
def solve(N, arr):
items_dict = Counter(arr)
counts = sorted(list(items_dict.values()))
n = len(counts)
# Precompute prefix sums
prefix_sums = [0] * (n + 1)
for i in range(n):
prefix_sums[i + 1] = prefix_sums[i] + counts[i]
for i in range(1, N+1):
ans = max_partitions(items_dict, i, prefix_sums, counts)
print(ans)
def main():
n = int(sys.stdin.readline().strip())
arr = list(map(int, sys.stdin.readline().strip().split()))
solve(n, arr)
if __name__ == "__main__":
main()
Related
- color balls
- simpler version of the problem