当前位置: 首页 > news >正文

题解:小S与机房里的电脑 Computer_C++算法竞赛_贪心_二分答案_模拟_数据结构

文章目录

  • 小S与机房里的电脑 Computer
    • 传统题
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例
      • 样例输入 1
      • 样例输出 1
      • 样例输入 2
      • 样例输出 2
    • 提示
    • 解题思路
    • AC Code
    • End

小S与机房里的电脑 Computer

传统题

  • 时间限制: 1000ms
  • 内存限制: 256MiB

题目描述

最近小S想带他的学生打组队娱乐赛,比赛规定每队三个人只能其中一个人用电脑进行代码的编写。

但是现在隔壁教室因为上大型集训课拿走了所有的充电器,导致最后只剩下一个充电器可以拿来充电。但是 n n n 个队伍需要 n n n 台电脑,并且组队娱乐赛要进行 m m m 分钟,每台电脑有初始的电量 a i a_i ai ,每分钟的耗电量 b i b_i bi 。没有办法,小S只能通过他的电路知识来改装这个充电器,使得它具有足够的功率来帮助同学们完成这场比赛。

但是功率越大危险度越高,小S希望你帮他计算一下,充电器至少每分钟要充多少电才能满足大家的需求。

输入格式

  • 第一行一个正整数 T T T 代表多组数据的组数
  • 第二行两个整数 n n n m m m
  • 第三行 n n n 个整数 a i a_i ai
  • 第四行 n n n 个整数 b i b_i bi

输出格式

输出一行整数,代表满足比赛需求的充电器每分钟最小的充电量,若无法满足需求,则输出 -1。

样例

样例输入 1

2
2 4
3 2
4 2
2 2
2 10
3 15

样例输出 1

5
-1

样例输入 2

2
1 5
4
2
1 6
4
2

样例输出 2

1
2

提示

全部数据包括:

  • n ≤ 2 × 1 0 5 n \leq 2 \times 10^5 n2×105
  • 1 ≤ m ≤ 2 × 1 0 5 1 \leq m \leq 2 \times 10^5 1m2×105
  • 1 ≤ a i ≤ 1 0 12 1 \leq a_i \leq 10^{12} 1ai1012
  • 1 ≤ b i ≤ 1 0 7 1 \leq b_i \leq 10^7 1bi107

其中,30%的数据保证 n ≤ 100 n \leq 100 n100


解题思路

提示:这里光看有些抽象,结合下面的 Code 理解起来更容易。

思路:考虑二分答案,二分最小的充电功率。

其中可以用 vector 建桶, v e s [ i ] ves[i] ves[i] 表示存活时间到 i i i 的电脑的结构体下标数组,

去枚举 vector 的第一维下标,同时设置一个变量 n o w T nowT nowT 表示当前时间,

根据贪心的思想,选择当前快要没电的那个:存活时间到 i i i 的先充电

如果当前时间大于第一维下标,说明电脑修不过来了,返回 false;

否则, n o w T = m nowT =m nowT=m 时,说明执行完任务了,退出。

小总结

check 中的循环调换了常理。原本正常的思路应该是枚举 n o w T nowT nowT,用堆维护当前的最小存活时间(如 AC 代码下面的代码),

但是这样复杂度 O ( log ⁡ ( 1 0 12 ) × m × log ⁡ ( n ) ) O(\log(10^{12}) \times m \times \log(n)) O(log(1012)×m×log(n)),但“好心”的出题人卡 log,说明不能这样。

于是,我们转而枚举第一维下标解决了问题,这种思路很值得积累。


程序运行过程:

  1. 输入,用结构体存储每一台电脑的基础信息和存活时间。
  2. 二分答案,充电功率,往小了二分。

check(){

  1. 预处理每一台电脑,用 vector 建桶,这样查询插入复杂度 O ( 1 ) O(1) O(1)
  2. 不断枚举 vector 的第一维下标,不断修电脑,直到有的电脑最大存活时间小于当前枚举的时间,退出。
  3. 一直执行至 n o w T = m nowT = m nowT=m,说明可以完成任务,返回 TRUE。

}

AC Code

这道题貌似要加快读,不然会被卡常。快读讲解文章

#include <bits/stdc++.h>
using namespace std;typedef long long ll;int T, n, m;struct Node{ll a, b;ll t_a; // 表示当前还能存活多长时间
}N[100005];
vector <int> A[100005];bool check(ll x){for(int i = 0; i <= m; i ++) A[i].clear(); // 先清空,后使用for(int i = 1; i <= n; i ++){ // 初始化赋值N[i].t_a = N[i].a;if(N[i].b != 0 && N[i].t_a / N[i].b + 1 <= m){ // 如果存活时间在m之内,说明还有计算的必要(它可能会撑不住)A[N[i].t_a / N[i].b + 1].push_back(i); // 塞到对应的桶中}}int nowT = 1; // 当前时间的计数器for(int i = 1; i <= m; i ++){ // 枚举m个时间单位,作为判断标准(可以理解为理想化的时间)while(A[i].size() > 0){ // 这个内层循环最多执行n次,所以总时间复杂度不是O(n^2),是线性O(n)的if(nowT > i){ // 如果当前时间>i,说明已经超时了return false;}if(nowT == m){return true; // 说明顺利执行完m秒,可以返回}int pos = A[i].back(); A[i].pop_back();N[pos].t_a += x; // 把充电器给他充上。因为当前的压线时间是i,所以肯定要先给快没电的(也就是当前时间i)充电。至于先后顺序就无所谓了。nowT ++;if(N[pos].t_a / N[pos].b + 1 <= 1LL * m){ // 注意a[i]<=1e12,m不强转ll可能会出问题A[N[pos].t_a / N[pos].b + 1].push_back(pos);}
//			cout << "debug: " << i << " " << A[i].size() << " " << nowT << endl;}
//		cout << "debug_i:" << i << endl;}return true;
}template <typename T>
void read(T &w){ // 防止卡常,加快读w = 0;char c = getchar();for(; c < '0' || c > '9'; c = getchar());for(; c >= '0' && c <= '9'; c = getchar()){w = (w << 1) + (w << 3) + (c ^ 48);}
}int main()
{for(read(T); T --; ){read(n), read(m);for(int i = 1; i <= n; i ++){read(N[i].a);}for(int i = 1; i <= n; i ++){read(N[i].b);}
//		cout << check(10) << endl;ll l = 0, r = 1e12, ans = -1;while(l <= r){ll mid = (l + r) >> 1;if(check(mid)){ans = mid;r = mid - 1;}else{l = mid + 1;}}printf("%lld\n", ans);}return 0;
}

附:上面提到的被卡超时的代码

//超时TLE
#include <bits/stdc++.h>
using namespace std;typedef long long ll;const int MAXN = 2e5 + 7;int T , n , m;struct Node{ll a , b;ll t_a;
}no[MAXN];bool check(ll x){map < int , vector <int> > vis;for(int i = 1; i <= n; i ++){ //预处理no[i].t_a = no[i].a;if(no[i].b != 0 && no[i].t_a / no[i].b < 1LL * m){vis[no[i].t_a / no[i].b].push_back(i);}else{//pass}}for(int tim = 0; tim < m; tim ++){if(vis.empty()){return true;}int pos = vis.begin()->first;if(pos < tim){return false;}ll t1 = vis[pos].back(); vis[pos].pop_back();if(vis[pos].size() == 0){vis.erase(vis.begin());}no[t1].t_a += x;if(no[t1].t_a / no[t1].b < m){vis[no[t1].t_a / no[t1].b].push_back(t1);}}return true;
}int main()
{for(scanf("%d" , &T); T; --T){scanf("%d %d" , &n , &m);for(int i = 1; i <= n; i ++){scanf("%lld" , &no[i].a);}for(int i = 1; i <= n; i ++){scanf("%lld" , &no[i].b);}
//		cout << check(5) << endl;ll l = 0 , r = 1e12 , ans = -1;while(l <= r){ //二分充电功率,往小了二分ll mid = (l + r) >> 1;if(check(mid)){ans = mid;r = mid - 1;}else{l = mid + 1;}}printf("%lld\n" , ans);}return 0;
}

End

感谢大家观看,祝大家 AC!

这里是 YLCHUP,拜拜ヾ(•ω•`)o

广告:本文在洛谷博客同步发送,个人洛谷账号:ylch

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 分布式IO系统2通道串口通信模块M602x
  • 昇思25天学习打卡营第16天 | Vision Transformer图像分类
  • JavaWeb入门程序解析(Spring官方骨架、配置起步依赖、SpringBoot父工程、内嵌Tomcat)
  • 2、电脑各部件品牌介绍 - 计算机硬件品牌系列文章
  • 数据结构(Java):力扣 二叉树面试OJ题(二)【进阶】
  • NLP篇5:自然语言处理预训练
  • 【python】多种回归算法对比气温预测
  • 云计算监控减少网络安全事件的五种方法
  • LinuxShell编程1———shell基础命令
  • 打印室预约小程序的设计
  • 【C++】类和对象·this指针
  • 科技出海|百分点科技智慧政务解决方案亮相非洲展会
  • HLS加密技术:保障流媒体内容安全的利器
  • WebAssembly与JavaScript的交互(1)
  • Mongodb文本索引
  • [deviceone开发]-do_Webview的基本示例
  • 《Java编程思想》读书笔记-对象导论
  • 【知识碎片】第三方登录弹窗效果
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • Flex布局到底解决了什么问题
  • Javascript Math对象和Date对象常用方法详解
  • php ci框架整合银盛支付
  • Spark RDD学习: aggregate函数
  • Spring Cloud中负载均衡器概览
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • Xmanager 远程桌面 CentOS 7
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 将 Measurements 和 Units 应用到物理学
  • 码农张的Bug人生 - 见面之礼
  • 区块链技术特点之去中心化特性
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 用jquery写贪吃蛇
  • 怎么将电脑中的声音录制成WAV格式
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 白色的风信子
  • 1.Ext JS 建立web开发工程
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (6)STL算法之转换
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (el-Transfer)操作(不使用 ts):Element-plus 中 Select 组件动态设置 options 值需求的解决过程
  • (搬运以学习)flask 上下文的实现
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (强烈推荐)移动端音视频从零到上手(下)
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像
  • (十一)图像的罗伯特梯度锐化
  • (实战篇)如何缓存数据
  • (算法)硬币问题
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • .NET 8 跨平台高性能边缘采集网关
  • .Net Memory Profiler的使用举例