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

二分答案合辑

kotori的设备

题目背景

kotori 有 n n n 个可同时使用的设备。

题目描述

i i i 个设备每秒消耗 a i a_i ai 个单位能量。能量的使用是连续的,也就是说能量不是某时刻突然消耗的,而是匀速消耗。也就是说,对于任意实数,在 k k k 秒内消耗的能量均为 k × a i k\times a_i k×ai 单位。在开始的时候第 i i i 个设备里存储着 b i b_i bi 个单位能量。

同时 kotori 又有一个可以给任意一个设备充电的充电宝,每秒可以给接通的设备充能 p p p 个单位,充能也是连续的,不再赘述。你可以在任意时间给任意一个设备充能,从一个设备切换到另一个设备的时间忽略不计。

kotori 想把这些设备一起使用,直到其中有设备能量降为 0 0 0。所以 kotori 想知道,在充电器的作用下,她最多能将这些设备一起使用多久。

输入格式

第一行给出两个整数 n , p n,p n,p

接下来 n n n 行,每行表示一个设备,给出两个整数,分别是这个设备的 a i a_i ai b i b_i bi

输出格式

如果 kotori 可以无限使用这些设备,输出 − 1 -1 1

否则输出 kotori 在其中一个设备能量降为 0 0 0 之前最多能使用多久。

设你的答案为 a a a,标准答案为 b b b,只有当 a , b a,b a,b 满足
∣ a − b ∣ max ⁡ ( 1 , b ) ≤ 1 0 − 4 \dfrac{|a-b|}{\max(1,b)} \leq 10^{-4} max(1,b)ab104 的时候,你能得到本测试点的满分。

样例 #1

样例输入 #1

2 1
2 2
2 1000

样例输出 #1

2.0000000000

样例 #2

样例输入 #2

1 100
1 1

样例输出 #2

-1

样例 #3

样例输入 #3

3 5
4 3
5 2
6 1

样例输出 #3

0.5000000000

提示

对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 100000 1\leq n\leq 100000 1n100000 1 ≤ p ≤ 100000 1\leq p\leq 100000 1p100000 1 ≤ a i , b i ≤ 100000 1\leq a_i,b_i\leq100000 1ai,bi100000

题解:

#include <iostream>
using namespace std;
int n;
double p, a[100001], b[100001], sp = 0;

bool check(float x) {
    double sum = 0;
    for (int i = 1; i <= n; i++) {
        if (a[i] * x > b[i]) {
            sum += x * a[i] - b[i];
        }
    }
    return sum <= p * x;
}

double bsearch() {
    double l = 0, r = 1e10, mid;
    while (r - l > 0.000001) {
        mid = (l + r) / 2;
        if (check(mid)) {
            l = mid;
        }
        else {
            r = mid;
        }
    }
    return l;
}

int main()
{
    cin >> n >> p;
    for (int i = 1; i <= n; i++) {
        cin >> a[i] >> b[i];
        sp += a[i];
    }
    if (sp <= p) {
        cout << -1;
    }
    else {
        cout << bsearch();
    }
    return 0;
}

思路:

这一题采用二分答案的方法来做,为什么会想到使用这个方法呢?

  • 首先,题目要求的是最多能将这些设备一起使用多久,按我的理解就是,求最短时间的最大值。
  • 要将所有设备一起使用,不管充电也好,不充电也罢,只要其中能量最少的设备没电了,就停止计时,现在便是求这个最少能量耗完(算上充了电)所要的时间。
  • 这和二分答案的判断条件吻合,所以使用二分答案。

现在便枚举最多可以使用k秒,k的枚举范围是[0,1e10],使左右边界逼近正确答案。只要r-l<0.000001我们就认为已经找到了正确答案,因为答案是允许误差存在的。

那么check函数该如何写呢?

  • 对于每个k,我们可以计算出在这k秒内,充电宝能够给这些设备提供k*p个单位的能量。
  • 由于充能是连续的,可以在设备间无缝切换的充电,所以只需要求使这些设备一起使用到k秒需要充的电的总和(当然,如果该设备本来储存有的电量就足够使用到k秒,便不需要充电了),然后将这个总和与k*p比较即可。
  • 如果总和大于k*p说明充的电量不够,也就是用不了那么久,那么就应该把k调小一些,左移右边界。
  • 如果总和小于k*p说明充的电量过剩了,使用时间还可以更久,就把k调大一些;如果总和刚好等于k*p,那么说明找到了一个答案,但是题目要求k的最大值,于是我们保留这个答案,继续寻找更优的解,右移左边界。

然后题目还指出了是存在无限使用的情况的,显然,这种情况只会出现充电速度极快的时候,快到供应过剩,也就是所有设备耗能的速度加起来还小于或等于充电的速度,此种情况需要特判。

-----------END------------

数列分段 Section II

题目描述

对于给定的一个长度为N的正整数数列 A 1 ∼ N A_{1\sim N} A1N,现要将其分成 M M M M ≤ N M\leq N MN)段,并要求每段连续,且每段和的最大值最小。

关于最大值最小:

例如一数列 4   2   4   5   1 4\ 2\ 4\ 5\ 1 4 2 4 5 1 要分成 3 3 3 段。

将其如下分段:

[ 4   2 ] [ 4   5 ] [ 1 ] [4\ 2][4\ 5][1] [4 2][4 5][1]

第一段和为 6 6 6,第 2 2 2 段和为 9 9 9,第 3 3 3 段和为 1 1 1,和最大值为 9 9 9

将其如下分段:

[ 4 ] [ 2   4 ] [ 5   1 ] [4][2\ 4][5\ 1] [4][2 4][5 1]

第一段和为 4 4 4,第 2 2 2 段和为 6 6 6,第 3 3 3 段和为 6 6 6,和最大值为 6 6 6

并且无论如何分段,最大值不会小于 6 6 6

所以可以得到要将数列 4   2   4   5   1 4\ 2\ 4\ 5\ 1 4 2 4 5 1 要分成 3 3 3 段,每段和的最大值最小为 6 6 6

输入格式

1 1 1 行包含两个正整数 N , M N,M N,M

2 2 2 行包含 N N N 个空格隔开的非负整数 A i A_i Ai,含义如题目所述。

输出格式

一个正整数,即每段和最大值最小为多少。

样例 #1

样例输入 #1

5 3
4 2 4 5 1

样例输出 #1

6

提示

对于 20 % 20\% 20% 的数据, N ≤ 10 N\leq 10 N10

对于 40 % 40\% 40% 的数据, N ≤ 1000 N\leq 1000 N1000

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1 0 5 1\leq N\leq 10^5 1N105 M ≤ N M\leq N MN A i < 1 0 8 A_i < 10^8 Ai<108, 答案不超过 1 0 9 10^9 109

题解:

#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
int N, M, a[100001], ans, maxa = -1;

bool check(int x) {
    int t = 1, sum = a[1];
    for (int i = 2; i <= N; i++) {
        if (sum + a[i] <= x) {
            sum += a[i];
        }
        else {
            sum = a[i];
            t++;
        }
    }
    return t <= M;
}

int bsearch() {
    int l = maxa, r = 1e9, mid;
    while (l < r) {
        mid = l + (r - l) / 2;
        if (check(mid)) {
            r = mid;
        }
        else {
            l = mid + 1;
        }
    }
    return l;
}

signed main()
{
    cin>> N >> M;
    for (int i = 1; i <= N; i++) {
        cin >> a[i];
        maxa = max(maxa, a[i]);
    }
    cout << bsearch();
    return 0;
}

思路:

这题同样是使用二分答案来做:

  • 首先确定枚举的答案范围,由于Ai都是非负整数,那么最坏的情况就是最大的子段和为这堆元素中的最大值,最好的情况嘛,题目说了答案不超过1e9,就拿这个当右边界就好了。
  • 然后check函数的写法,大致就是,先默认分的段数为1段,定义一个t存储数组被分成的段数,定义一个sum暂时记录当前子段的和,然后遍历A数组,每遍历到一个就判断sum+A[i]是否>=x,如果是,就sum+=A[i],遍历下一个元素;如果不是,就说明在此处要分段了,则段数++,sum=A[i]。
  • 最后判断t和M的大小,如果t大于M说明枚举的答案太小了,调大些,反之,调小一些。

相关文章:

  • Eclipse Theia技术揭秘——自定义布局
  • 机器学习模型4——聚类1(k-Means聚类)
  • React 学习笔记总结(二)
  • ssh登陆概率性失败,报错:kex_exchange_identification
  • 微服务项目:尚融宝(60)(核心业务流程:个人中心)
  • 【P8179】【EZEC-11】Tyres(背包问题,决策单调性,分治)
  • <Linux复习>权限概念上
  • 嵌入式开发:嵌入式安全的6个要点
  • 第2章 Linux的Shell基础(一)
  • 0926物体检测和数据集
  • 【PAT甲级】1064 Complete Binary Search Tree
  • ASEMI快恢复二极管FR207参数,FR207图片,FR207应用
  • Golang常见面试题及解答
  • 全网最牛的使用python快速搭建接口自动化测试脚本实战总结
  • 湖仓一体电商项目(二十三):离线业务 统计每天用户商品浏览所获积分
  • [ JavaScript ] 数据结构与算法 —— 链表
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • android图片蒙层
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • flask接收请求并推入栈
  • HomeBrew常规使用教程
  • JavaScript DOM 10 - 滚动
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • PHP的类修饰符与访问修饰符
  • SegmentFault 2015 Top Rank
  • storm drpc实例
  • Vue2.x学习三:事件处理生命周期钩子
  • Vue实战(四)登录/注册页的实现
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 创建一个Struts2项目maven 方式
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 对JS继承的一点思考
  • 解析 Webpack中import、require、按需加载的执行过程
  • 今年的LC3大会没了?
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 探索 JS 中的模块化
  • 赢得Docker挑战最佳实践
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • #NOIP 2014# day.2 T2 寻找道路
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (16)Reactor的测试——响应式Spring的道法术器
  • (30)数组元素和与数字和的绝对差
  • (Java)【深基9.例1】选举学生会
  • (windows2012共享文件夹和防火墙设置
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (十六)串口UART
  • (四)图像的%2线性拉伸
  • (一)kafka实战——kafka源码编译启动
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)关于多人操作数据的处理策略
  • (转)树状数组
  • .gitignore文件_Git:.gitignore