自学内容网 自学内容网

2024年码蹄杯专科组第一场初赛 解题报告 | 珂学家


前言

在这里插入图片描述


题解

这是码蹄杯2024年专科组的第一场初赛,整体下来相对比较简单。

有一道0-1分数规划(拔河)不错,一道模拟题(云顶之奕)还行。


拔河

难度: 钻石

思路: 0-1分数规划 + 前缀和单调队列优化

板子题,如果之前没做过类似的0-1分数规划题,那就很难了,这题可以作为本场的压轴题。

一般对于子数组的平均数最值问题

  • 采用二分思路
  • 然后把题转化为0-1判定问题

对于check的核心逻辑

相当于重构数组 b r r [ i ] = a r r [ i ] − a v g brr[i]=arr[i] - avg brr[i]=arr[i]avg,

存在一个子区间

∑ t = i t = j b r r [ t ] > = 0 , j − i + 1 ≥ k \sum_{t=i}^{t=j} brr[t] >= 0, j - i + 1 \ge k t=it=jbrr[t]>=0,ji+1k

#include<bits/stdc++.h> 

using namespace std;

int main( )
{
    // 0-1分数规划
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n, f;
    cin >> n >> f;
    vector<int> arr(n);
    for (int &x: arr) cin >> x;

    // 核心check逻辑
    function<bool(double)> check = [&](double avg) {
        double acc = 0;
        for (int i = 0; i < f - 1; i++) {
            acc += (arr[i] - avg);
        }
        // 保证窗口大于f
        // 单调队列优化,保持前缀和的最小值即可
        double preF = 0;
        double preMin = 0;
        for (int i = f - 1; i < n; i++) {
            acc += (arr[i] - avg);
            if (acc - preMin >= 0) return true;
            preF += (arr[i - f + 1] - avg);
            preMin = min(preMin, preF);
        }
        return false;
    };

    // 二分
    double l = 0, r = 2000;
    while (r - l > 1e-6) {
        double m = (l + r) / 2.0;
        if (check(m)) {
            l = m;
        } else {
            r = m;
        }
    }    
    cout << (int)(r * 1000) << endl;
    return 0;
}

云顶之奕

难度: 钻石

思路: 模拟题

它的题意,有些地方还是需要加强

  • 最多8个位子,如果新加入,不能产生合并,就会被忽略

比如当前为{1,2,3,4,5,10,20,30}, 此时新来一个1,因为8位子满了,就会被忽略

#include<bits/stdc++.h> 

using namespace std;

struct Game {
    int cap;
    map<int, int> hp;

    Game() : cap(0) {}
    void add(int v) {
        if (cap < 8 || (v < 100 && (hp[v] + 1) % 3 == 0)) {
            cap += 1;
            hp[v]++;
            while (v < 100 && hp[v] % 3 == 0) {
                hp[v] = 0;
                hp[v * 10]++;
                v = v * 10;
                cap -= 2;
            }
        }
    }

    int maxValue() {
        int r = 0;
        for (auto &[k, v] : hp) {
            if (v > 0) r = max(r, k);
        }
        return r;
    }
};

int main( )
{
    Game game;
    // 备战席,固定为8
    for (int i = 0; i < 8; i++) {
        int v;
        cin >> v;
        game.add(v);
    }
    // 备选席(流水)
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        int v;
        cin >> v;
        game.add(v);
    }

    int m;
    cin >> m;
    if (game.maxValue() >= m) {
        cout << "YES YES YES" << endl;
    } else {
        cout << "NO NO NO" << endl;
    }
    
    return 0;
}

写在最后

在这里插入图片描述


原文地址:https://blog.csdn.net/m0_66102593/article/details/140628722

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!