2022ICPC区域赛济南站

补题链接QOJ:The 2022 ICPC Asia Jinan Regional Contest - Dashboard - Contest - QOJ.ac

K. Stack Sort

思路:考虑 a 需要比 a+1 先出栈,所以如果读到 a,发现 a+1 还没被记录则需要多建一个栈。

void solve()
{
    int n;
    cin >> n;
    int num = 0;

    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        if (!vis[a[i] + 1])
        {
            num++;
        }
        vis[a[i]] = 1;
    }
    cout << num << '\n';
    for (int i = 1; i <= n; i++)
    {
        vis[i] = 0;
    }
}

M. Best Carry Player

思路:与顺序无关,只需要模拟过程进位几次。需要注意连续进位。

void solve()
{
    int n;
    cin >> n;
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    auto add = [&](auto x, auto y)
    {
        int sum = x + y;
        auto n1 = 0, n2 = 0;
        while (x != 0 || y != 0)
        {
            n1 += x % 10;  //记录上一位是否有进位
            x /= 10;
            n2 = y % 10;
            y /= 10;
            ans += (n1 + n2 >= 10) ? 1 : 0;
            n1 = (n1 + n2 >= 10) ? 1 : 0;

            // cerr<<x<<' '<<y<<' '<<ans<<' '<<n1<<' '<<n2<<'\n';
        }
        return sum;
    };
    int st = a[1];
    for (int i = 2; i <= n; i++)
    {
        st = add(st, a[i]);
    }
    cout << ans << '\n';
}

E. Identical Parity

思路:先特判,k=1时除了n=1都不合法;k为偶数一定合法,直接奇偶相间输出;

所以只需要分析k为奇数的情况。

题目相当于在i i+k i+2k·····等位置上放置奇偶性相同的数,共有k个完整组。

首先我们可以根据n的大小计算1-n的奇数和偶数个数;

然后因为k是奇数,对于放奇数的位置,我们分出k/2+1组;偶数则为k/2组。

然后计算剩余的奇偶数是否满足放置条件即可。

[2022icpc济南 ADEKM - 知乎](https://zhuanlan.zhihu.com/p/590527069) 讲的很清晰。

void solve()
{
    cin >> n >> k;

    if (n == 1)
    {
        yes;
        re;
    }
    if (k == 1)
    {
        no;
        re;
    }
    if (k % 2 == 0)
    {
        yes;
        re;
    }
    int odd = (n + 1) / 2, even = n / 2; // 计算n中奇偶数个数
    int ke = k / 2, ko = k / 2 + 1;      // 因为k是奇数,我们令偶数占小的一半
    int zu = n / k;                      // 每组分配的个数,因为每一组填入的奇偶性相同
    int yu = n % k;                      // 分配后剩下的数
    int yuodd = odd - ko * zu, yueven = even - ke * zu;
    //奇数余数=奇数总数-k/2+1个奇数组*每组填入个数,偶数余数同理
    if (yuodd >= 0 && yueven >= 0 && yueven + yuodd == yu)
    {
        if (yuodd <= ko && yueven <= ke)//确保余数要小于对应组数
        {
            yes;
            re;
        }
        no;
        re;
    }
    no;
    re;
}

A. Tower

思路:一个trick:给定一个数组,通过 ±1 使所有数相同,最小操作是变成中位数。

现在多了一个/2操作,不确定中位数会是哪个,但能保证结果在这些数之间,所以暴力枚举求最小值。

比如 如果设目标位x,起始位a,让a->x。

  • a<x 只能通过+1到达
  • a>x 我们可以考虑先/后±或者先±后/,可以证明前者一定不劣于后者。
void solve()
{
    cin >> n >> k;
    set<int> st;
    rep(1, i, n)
    {
        cin >> a[i];
        x = a[i];
        while (x)
        {
            st.insert(x);
            x /= 2;
        }
    }
    minn = 1e18;
    for (auto i : st)
    {

        rep(1, j, n)
        {
            if (a[j] <= i)
            {
                b[j] = i - a[j];
            }
            else
            {
                num = 0;
                x = a[j];
                while (x / 2 >= i)
                {
                    x /= 2;
                    num++;
                }
               b[j] = min(num + (x - i), num + 1 + (i - x / 2)); //分别考虑不除以和除以2
            }
        }
        ans = 0;
        sort(b + 1, b + 1 + n);
        rep(1, i, n - k)
        {
            ans += b[i];
        }
        minn = min(ans, minn);
    }

    cout << minn;
}
posted @ 2025-10-20 12:45  lengling  阅读(21)  评论(0)    收藏  举报