Number Game (Codeforces 1749C)
Tags: Greedy, games

Alice and Bob are playing a game. They have an array of positive integers $$$a$$$ of size $$$n$$$.Before starting the game, Alice chooses an integer $$$k \ge 0$$$. The game lasts for $$$k$$$ stages, the stages are numbered from $$$1$$$ to $$$k$$$. During the $$$i$$$-th stage, Alice must remove an element from the array that is less than or equal to $$$k - i + 1$$$. After that, if the array is not empty, Bob must add $$$k - i + 1$$$ to an arbitrary element of the array. Note that both Alice's move and Bob's move are two parts of the same stage of the game. If Alice can't delete an element during some stage, she loses. If the $$$k$$$-th stage ends and Alice hasn't lost yet, she wins.Your task is to determine the maximum value of $$$k$$$ such that Alice can win if both players play optimally. Bob plays against Alice, so he tries to make her lose the game, if it's possible.

Input: The first line contains a single integer $$$t$$$ ($$$1 \le t \le 100$$$) — the number of test cases.The first line of each test case contains a single integer $$$n$$$ ($$$1 \le n \le 100$$$) — the size of the array $$$a$$$.The second line contains $$$n$$$ integers $$$a_1, a_2, \dots, a_n$$$ ($$$1 \le a_i \le n$$$).

Output: For each test case, print one integer — the maximum value of $$$k$$$ such that Alice can win if both players play optimally.


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

Sample Outputs:
2
0
1
3

Solution (Python):
def turn(p):
    return p // 2 + p % 2

def s():
    input()
    a = [int(i) for i in input().split()]
    c = a.count(1)
    l = sorted(a)
    if c <= 1:
        return c
    remaining = c - 1
    p = c // 2 + 1
    tot = c
    lost = 2
    for k in l:
        if k > p or remaining < 1:
            break
        if k == 1:
            continue
        remaining -= 1
        if k > lost:
            remaining -= k - lost
            lost = k + 1
        else:
            lost += 1
        tot += 1
        p = tot // 2 + 1
    return tot // 2 + tot % 2
x = int(input())
for y in range(x):
    print(s())

Solution (Python):
import math

def main():
    n = int(input())
    l = list(map(int, input().split()))
    l = sorted(l)
    i = math.ceil(n / 2)
    for k in range(i):
        m = k * 2 + 1
        l2 = l[0:m]
        for j in range(k + 1):
            if l2[-1] <= k - j + 1:
                l2.pop(len(l2) - 1)
            else:
                print(k)
                return
            if j != k:
                l2[j] = k - j + 1
    print(k + 1)
    return
for i in range(int(input())):
    main()

Solution (Python):
t = int(input())
for _ in range(t):
    n = int(input())
    a = list(map(int, input().split(' ')))
    a.insert(0, -1)
    a.sort()
    possible = True
    for k in range(n + 1):
        if 2 * k - 1 > n:
            possible = False
            print(k - 1)
            break
        for i in range(1, k + 1):
            if not a[2 * k - 1 - i + 1] <= k - i + 1:
                possible = False
                break
        if not possible:
            print(k - 1)
            break
    if possible:
        print(n)