USACO历年青铜组真题解析 | 2023年12月Candy Cane Feast

学习C++从娃娃抓起!记录下USACO(美国信息学奥赛)备考青铜组别比赛学习过程中的题目,记录每一个瞬间。

附上汇总贴:USACO历年青铜组真题解析 | 汇总-CSDN博客


【题目描述】

农夫约翰(FJ)的奶牛非常喜欢吃甜食,尤其喜欢吃拐杖糖!FJ共有N头奶牛,每头奶牛都有一定的初始身高,他想喂养它们M根拐杖糖,每根拐杖糖也有不同的高度(1≤N,M≤2⋅105)。

FJ计划按照输入给出的顺序,一根接一根地把拐杖糖喂给奶牛。为了给他的奶牛喂食拐杖糖,他会把拐杖糖悬挂起来,让拐杖糖的底部刚好碰到地面。然后,奶牛们会按输入给出的顺序一个接一个地排队,走向拐杖糖,每只奶牛都会把自己高度所及的部分的拐杖糖吃掉(因为它们无法触及更高的部分)。即使在奶牛吃掉了底部的拐杖糖之后, 拐杖糖会仍然悬挂在最初竖立的地方,并不会下降到地面上。如果拐杖糖的底部已经高于某只奶牛的身高, 那么这只奶牛可能在轮到她时什么也不吃。在每头奶牛都吃了一次之后,奶牛的身高会随着它们吃了多少单位的拐杖糖而增长,并且农夫约翰会挂上下一根拐杖糖(底部仍然刚好碰到地面), 奶牛们再次重复此过程(11号奶牛再次第一个开始吃下一根拐杖糖)。

【输入】

第一行包含NM

第二行包含N头奶牛的初始身高,每个身高都在[1,10^9]的范围内。

第三行包含M根拐杖糖的高度,每个高度都在[1,10^9]的范围内。

【输出】

一共N行,每行一个数字,表示N头奶牛的最终身高。

【输入样例】

3 2
3 2 5
6 1

【输出样例】

7
2
7

【代码详解】

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m;
ll a[200005];
struct node {
    int top, bottom;
}b[200005];
int main()
{
    cin >> n >> m;  // 输入n和m
    for (int i=1; i<=n; i++) {  // 输入n个奶牛的身高
        cin >> a[i];
    }
    for (int i=1; i<=m; i++) {  // 输入m个拐杖糖的高度
        cin >> b[i].top;  // 输入拐杖糖的高度
        b[i].bottom = 0;  // 同时记录该拐杖糖的底部为0
    }
    for (int i=1; i<=m; i++) {  // 先遍历m再遍历n(反过来会超时,部分测试点会TLE)
        for (int j=1; j<=n; j++) {  
            if (b[i].top==0) break;  // 如果该拐杖糖已经被吃掉了,则跳过该糖(就是通过该行代码减少了时间复杂度)
            if (a[j]<=b[i].bottom) continue;  // 如果奶牛高度小于糖的底部高度,则说明没法吃到,继续循环
            if (a[j]>=b[i].bottom && a[j]<b[i].top) {  // 如果奶牛高度在糖的高度中间
                int tmp = a[j];  // 记录奶牛高度
                a[j] = a[j] + (a[j]-b[i].bottom);  // 奶牛高度增加吃掉的糖的高度
                b[i].bottom = tmp;  // 将糖的底部高度更新为奶牛的高度
            } else if (a[j]>=b[i].top) {  // 如果奶牛比糖的top位置还高
                a[j] = a[j] + (b[i].top-b[i].bottom);  // 则奶牛高度增加糖的长度(top-bottom)
                b[i].top = 0;  // 将糖的top修改为0,即被吃掉
            }
        }
    }
    for (int i=1; i<=n; i++) {  // 输出所有奶牛高度
        cout << a[i] << endl;
    }
    return 0;
}

【运行结果】

3 2
3 2 5
6 1
7
2
7
  • 20
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
USACO2022金组是国际在线判题系统USACO的最高级别,题目难度较高,在该比赛中取得好成绩是一项巨大的成就。以下是对该比赛的一些题目解析。 第一题:“交通计划” 题目要求:给定一个n个节点的有向图,每条边有一个长度,希望添加最少的边使得所有节点连通,求最小生成树的权值和。 解析:该题可以使用Kruskal算法求解,将每条边按权值从小到大排序,再依次加入,判断加入的边是否会形成环,若形成则不加入,直到所有节点连通为止。此时Kruskal算法得到的最小生成树的权值和即为所求。 第二题:“点火计划” 题目要求:给定一个n个节点的有向图,每条边有一个权值和一个点火时长,每个节点有一个点火启动时刻和时刻结束时刻,希望从其中选出一些边点火,使得所有节点都可从点火的边出发到达,且所选点火边的总点火时长最小。 解析:该题可以使用最小费用最大流算法求解。将每条边看做一个容量为1,费用为点火时长的边,源点向节点的点火边容量为1,费用为0的边,节点的点火边向汇点的容量为1,费用为0的边,对这个网络进行最小费用最大流即可得到所选边的总点火时长最小。 第三题:“美味佳肴” 题目要求:给定n个菜品,每个菜品有它的权值和两个类别,希望选出k个菜品,使得选出的菜品数量在每个类别中都不超过$\frac{k}{3}$个,且所选菜品的权值和最大。 解析:该题可以使用动态规划求解。设$f[i][j][k]$表示前i个菜品中,选择j个一类菜品,选择k个二类菜品的最大权值和,状态转移方程为$f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][k]+a[i],f[i-1][j][k-1]+b[i])$,其中a[i]为i号菜品的权值,若为一类则为该权值,否则为0,b[i]为i号菜品的权值,若为二类则为该权值,否则为0。最终答案为$f[n][$k/3$][$k/3$]。 以上是对USACO2022金组的部分题目的解析,USACO比赛是全球范围内的计算机竞赛,竞争非常激烈,能够在该比赛中脱颖而出是一项非常棒的成就。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值