Pretty classic greedy problem to work on. Here is how to approach it:

1. "the smallest team is as large as possible." actually means, team members should be distributed as average as possible

2. When you are to put member with skill-level 'x', you find the team with least members (say n members), whose lowest skill-level is x + 1, and update the record.

With statement above, you can combine hashmap and min-heap to solve it:

#include <cmath>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <climits>
#include <iostream>
#include <algorithm>
#include <functional>
#include <queue>
#include <unordered_map>
#include <unordered_set>
using namespace std;

void go()
{
    int n; cin >> n;
    vector<int> in(n);
    for (int i = 0; i < n; i++)
        cin >> in[i];
    std::sort(in.begin(), in.end(), std::greater<int>());

    //    min-value: sizes in heap
    unordered_map<int, priority_queue<size_t, std::vector<size_t>, std::greater<size_t>>> rec;
    for (auto v : in)
    {
        if (rec.find(v + 1) == rec.end())
        {
            rec[v].push(1);
        }
        else
        {
            auto it = rec.find(v + 1);
            size_t old_minsize = it->second.top();
            it->second.pop();
            if (it->second.size() == 0)
            {
                rec.erase(v + 1);
            }
            rec[v].push(old_minsize + 1);
        }
    }

    //    Get min size
    size_t min_size = std::numeric_limits<size_t>::max();
    for (auto &r : rec)
        min_size = std::min(min_size, r.second.top());
    cout << (min_size == std::numeric_limits<size_t>::max() ? 0:min_size) << endl;
}

int main()
{
    int t; cin >> t;
    while (t--)
    {
        go();
    }
    return 0;
}