GDCPC 2024 Single Round Solution (PARTIAL)

GDCPC 2024 Single Round Solution (PARTIAL)

0. 感言

难。

题有 \(8\) 道,AC \(1\) 道。

身败名裂。

3. 乐乐买书

由题可设买 \(a\) 本黑书,\(b\) 本紫书,\(c\) 个糖果。

\[\begin{cases} 40a+39b+0.5c=n\\ a+b+c=n \end{cases} \]

上式减下式得

\[39a+38b=0.5c \]

代入上式得

\[79a+77b=n \]

求二元一次方程整数解数量即可。

时间复杂度 \(O(1)\)

#include <iostream>
using namespace std;
const int N = 1e5 + 10;
using ll = long long;
ll n, a, b, lw;
int main()
{
    scanf("%lld", &n);
    while (79 * a <= n and (n - 79 * a) % 77)
        a++;
    if (79 * a > n)
        return puts("0"), 0;
    b = (n - 79 * a) / 77;
    printf("%lld\n", min(n / 77 - a + 1, b / 79 + 1));
}

7. 比赛

二分答案。

设初始所有比赛结果均为平局。

则胜负操作改为 \(+2/-1\),且操作上限为 \(k\),而不要求必须为 \(k\)

二分答案 \(x\) ,则尽量增大包括 \(1\) 在内的 \((x+1)\) 个队伍的分值,减小其余 \((n-x-1)\) 个队伍的分值。

优先队列可做。

时间复杂度 \(O(nk\log^2 n)\)

#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
int n, k, a[N], tar, l, r;
using pii = pair<int, int>;
multiset<pii, greater<pii>> q;
inline bool check(int x)
{
    decltype(q)().swap(q);
    for (int i = 2; i <= n - x; i++)
    {
        q.insert({a[i], k});
    }
    if (!q.size())
        return true;
    for (int i = 1; i <= (x + 1) * k; i++)
    {
        if (!q.size())
            return true;
        auto tmp = *q.begin();
        q.erase(q.begin());
        tmp.first--, tmp.second--;
        if (!tmp.second)
        {
            if (tmp.first > tar)
                return false;
            continue;
        }
        q.insert(tmp);
    }
    while (q.size() > 1 and q.begin()->first > tar)
    {
        auto t1 = *q.begin(), t2 = *prev(q.end());
        q.erase(q.begin()), q.erase(prev(q.end()));
        t1.first--, t1.second--, t2.first += 2, t2.second--;
        if (t1.second)
            q.insert(t1);
        if (t2.first > tar)
            return false;
        if (t2.second)
        {
            q.insert(t2);
        }
    }
    return q.empty() or q.begin()->first <= tar;
}
int main()
{
    scanf("%d%d", &n, &k);
    r = n - 1;
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", a + i);
        a[i] += k;
    }
    tar = a[1] + 2 * k;
    sort(a + 2, a + n + 1);
    while (l < r)
    {
        int mid = (l + r) >> 1;
        if (check(mid))
            r = mid;
        else
            l = mid + 1;
    }
    printf("%d\n", r);
}
posted @ 2024-05-25 21:18  丝羽绫华  阅读(20)  评论(0编辑  收藏  举报