原题链接:蓝桥杯2022年第十三届决赛真题-卡牌
整体思路:
将现有牌数进行排序,先记录下此时最小牌数min,
那么想要增加一套牌,牌数最小的数字必须加一张手写牌
随后把牌数更新,同时判断后续牌数有没有也是min的;
如果没有就说明本次加入手写牌后整体就增加一套牌
如果有(例如初始牌数都是一样的)那就不急着增加套牌数,对这个牌进行同样的操作
注意事项:开long long
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
ll a[N];//a[i]是指 第i种牌最多能手写 a[i]张
//利用 multimap 以牌数进行排序,key会出现重复的情况
multimap<int,int> p;//对组p<某号牌现有的牌数,这组牌的初始下标> 初始下标是为了后续访问a[i]
ll n,m;
//ans是记录利用手写牌所能增加的套牌数,sum是记录初始时有多少套牌数
//最终的数就是二者之和
ll ans = 0,sum = 0;
void way(){//统计ans
if(m<=0) return;//已经没有手写牌了,就返回
auto bg = p.begin();//bg指向当前最小牌数的pair对组
int min = bg->first;//记录最小值方便后续判断是否算得上增加了一套牌
int dex = bg->second;//拿到这组牌的初始下标,便于访问a[i]查看他最多能加入几张手写牌
if(a[dex]>0){//只有剩余纸张大于0(m>0前面已经判断)且这个号牌还能加入手写牌(a[i]>0) 才加入手写牌
a[dex]--;//还能加入的手写牌数减1
m--;//总的纸张数减1
int temp = min;
temp++; //拿到他已有的牌数 加一张手写牌
p.erase(bg);//删除原来的数据
p.insert(pair<int,int>(temp,dex));//加入现在更新的数据
bg = p.begin();//重新让bg指向此时最小数牌的pair对组
}
else {//无法再加入手写牌就返回
return;
}
if(bg->first!=min) {//现在的最小牌数跟加入手写牌前的最小牌数不同
ans++;//增加的这一张手写牌可以让套牌数加1
}
way();//继续上述操作直到无法再加入手写牌
}
void solve(){
//数据初始化
cin>>n>>m;
for(int i=0;i<n;i++){
int j;
cin>>j;//初始牌数,i为初始下标与a[i]对应
p.insert(pair<int,int>(j,i));
}
sum = p.begin()->first;//拿到初始的套牌数 就是牌数最少的那个号牌的数量
for(int i=0;i<n;i++){
cin>>a[i];//a[i]记录对应牌的手写牌数量上限
}
way();//统计手写牌的加入能增加几个套牌数---ans
cout<<ans + sum;//总套牌数 = 初始套牌数 + 手写牌增加的套牌数
}
int main(){
solve();
return 0;
}0.0分
3 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复