蓝桥杯 / 卡牌 /c\c++

问题描述

这天,小明在整理他的卡牌。他一共有n 种卡牌,第 i 种卡牌上印有正整数数 i (i ∈[1,n]), 且第 i 种卡牌现有 ai 张 。 而如果有 n 张卡牌 ,其中每种卡牌各一张,那么这 n 张卡牌可以被称为一套牌。小明为了凑出尽可能多套牌,拿出了 m 张空白牌,他可以在上面写上数 i ,将其当作第 i 种牌来凑出套牌。然而小明觉得手写的牌不太美观。决定第 i 种牌最多手写 bi 张

请问小明最富哦能凑出多少套牌?

输入格式:

输入共三行,第一行为两个正整数n ,m。

第二行为n 个正整数a1,a2,...,an。

第三行为n 个正整数b1,b2,...,bn。

输出格式

一行,一个整数表示答案

样例输入

cpp 复制代码
4 5
1 2 3 4
5 5 5 5

样例输出

cpp 复制代码
3

样例说明

这5张空白牌中,拿2张写1 ,拿一张写2,这样每种牌的牌数就变为了3,3,3,4可以凑出3套牌,剩下的2张空白牌不能再帮助小明凑出一套。

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 200010;
int a[N], b[N];
int n;
LL m;

bool check(int mid)
{
  LL t = m;
  //尝试将牌分配
  for(int i = 1; i <= n; i ++ )
  {
    //如果牌的套数比当前拥有的牌数多,需要补充mid-a[i]张牌,如果满足可补充牌数b[i]足够则模拟补充
    if(mid > a[i] && b[i] >= mid - a[i])
    {
      t -= mid - a[i];
    } 
    //如果需要补充,但可补充的牌数不够,也无法完成补充,那自然也凑不出mid套牌
    else if (mid > a[i] && b[i] < mid - a[i]) return false;
    //空白牌不够用了自然也凑不出来
    if(t < 0) return false;
  }
  return true;
}

int main()
{
  cin >> n >> m;
  for(int i = 1; i <= n; i ++ ) cin >> a[i];
  for(int i = 1; i <= n; i ++ ) cin >> b[i];
  //求b[i]+a[i]的最小值minh
  int minh = a[1] + b[1];
  for(int i = 2; i <= n; i ++ )
  {
    int x = a[i] + b[i];
    if(x < minh)
      minh = x;
  }
  //我们尝试二分能凑成牌的套数,牌的套数取决于最小一组牌的数量,在没有m限制的情况下,补充后最小牌的数量就是minh,因此区间范围为[0,minh]
  int l = 0, r = minh;
  while(l < r)
  {
    int mid = l + r + 1 >> 1;
    //满足,表示mid符合条件,由于求最大值,更新左边界为mid
    if(check(mid)) l = mid;
    //不满足,表示mid太大了,更新右边界
    else r = mid - 1;
  }
  cout << l << endl;
  return 0;
}
cpp 复制代码
//堆排序的方法做复杂度为查找最小牌 o(log n) 和 插入次数 o(n) 
//  为 o(log n)*o(n)
//贪心为遍历4次的复杂度 + 排序一次复杂度
//  为 o(n) + o(log n)

//运用贪心算法,将牌从小到大排(保证前面的排小于后面的排)好序之后对前 i 张牌求和加上空白排
//再除以 i  (使加上空白排后前i张排都相等) 
//如果大于 i 下一个排的初始排量说明有多余的排可以继续由后面的排平摊

//求和要用到前缀和,注意每种牌可添加的上限 
#include<bits/stdc++.h>
using namespace std;
#define int long long

const int NUM = 2e5 + 10;
struct A{
    int x,y;
    bool operator < (const A &c) const{
        return x < c.x;
    }
};
A a[NUM];
int store[NUM];
int minn = 1e18;

signed main(){
    int n,m;
    cin>>n>>m;
    
    a[0].x = a[0].y = 0;
    for(int i=1;i<=n;i++) scanf("%lld",&a[i].x);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i].y);
    sort(a+1,a+n+1);

    //for(int i=1;i<=n;i++) cout<<a[i].x<<" "; cout<<endl;
    for(int i=1;i<=n;i++) store[i] = store[i-1] + a[i].x;
    //for(int i=1;i<=n;i++) cout<<store[i]<<" "; cout<<endl;
    
    for(int i=1;i<=n;i++){
        minn = min(a[i].y + a[i].x,minn);
        int ans = (store[i] + m) / i;
        if(i < n) if(ans > a[i+1].x) continue;
    
        if(ans <= minn) cout<<ans;
        else cout<<minn;
        break;
    } 
    
    return 0;
}
相关推荐
liuyang-neu9 小时前
力扣 11.盛最多水的容器
算法·leetcode·职场和发展
宇宙李13 小时前
2024java面试-软实力篇
面试·职场和发展
测试界柠檬14 小时前
接口测试到底测试什么?
自动化测试·软件测试·功能测试·程序人生·职场和发展·单元测试·压力测试
自身就是太阳15 小时前
2024蓝桥杯省B好题分析
算法·职场和发展·蓝桥杯
David猪大卫15 小时前
数据结构修炼——顺序表和链表的区别与联系
c语言·数据结构·学习·算法·leetcode·链表·蓝桥杯
Aurora200516 小时前
蓝桥杯2024省C
c语言·算法·蓝桥杯
源代码:趴菜21 小时前
LeetCode63:不同路径II
算法·leetcode·职场和发展
严格格1 天前
三范式,面试重点
数据库·面试·职场和发展
南加第一划水1 天前
Leetcode 每日一题:Evaluate Division
算法·leetcode·职场和发展
鱼跃鹰飞1 天前
Leetcode面试经典150题-130.被围绕的区域
java·算法·leetcode·面试·职场和发展·深度优先