2024AcWing蓝桥杯集训·每日一题-二分
1.[AcWing503.借教室]
题目描述
在大学期间,经常需要租借教室。
大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。
教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。
面对海量租借教室的信息,我们自然希望编程解决这个问题。
我们需要处理接下来
共有
我们假定,租借者对教室的大小、地点没有要求。
即对于每份订单,我们只需要每天提供
借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。
如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。
这里的无法满足指从第
现在我们需要知道,是否会有订单无法完全满足。
如果有,需要通知哪一个申请人修改订单。
输入格式
第一行包含两个正整数
第二行包含
接下来有
每行相邻的两个数之间均用一个空格隔开。
天数与订单均用从
输出格式
如果所有订单均可满足,则输出只有一行,包含一个整数
否则(订单无法完全满足)输出两行,第一行输出一个负整数
数据范围
输入样例
4 3
2 5 4 3
2 1 3
3 2 4
4 2 4
输出样例
-1
2
解题思路
首先每份订单需要教室是区间性质的,那么可以考虑前缀和和差分进行订单的预处理,处理得出每天需要的教室数量。
该问题需要求解是否存在订单无法满足,且教室分配是按照订单顺序,那么我们可以二分最后一个满足分配要求的订单,即该订单
C++代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
typedef long long LL;
int n, m;
int w[N], d[N], s[N], t[N];
LL b[N];
bool check(int k) {
memset(b, 0, sizeof b);
// 差分
for (int i = 1; i <= k; i++) {
b[s[i]] += d[i];
b[t[i] + 1] -= d[i];
}
LL sum = 0;
for (int i = 1; i <= n; i++) {
sum += b[i];
if (sum > w[i]) // 需大于供
return false;
}
return true;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &w[i]); // 每天供给的教室数量
for (int i = 1; i <= m; i++) scanf("%d%d%d", &d[i], &s[i], &t[i]); // 订单
int l = 0, r = m;
while (l < r) {
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
if (r == m) puts("0");
else printf("-1\n%d\n", r + 1);
return 0;
}
2.[AcWing5407.管道]
题目描述
有一根长度为
一开始管道是空的,位于
对于位于
求管道中每一段中间的传感器都检测到有水流的最早时间。
输入格式
输入的第一行包含两个整数
接下来
输出格式
输出一行包含一个整数表示答案。
数据范围
对于
对于
对于所有评测用例,
输入样例
3 10
1 1
6 5
10 2
输出样例
5
解题思路
二分时间,具体思路见代码注释。
C++代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
typedef pair<int, int> PII;
typedef long long LL;
int n, len;
int L[N], S[N];
PII a[N];
bool check(int mid) {
int cnt = 0;
for (int i = 1; i <= n; i++) {
if (S[i] <= mid) { // 打开时刻 ≤ mid
int t = mid - S[i];
int l = max(1, L[i] - t), r = min((LL) len, (LL) L[i] + t);
a[cnt++] = {l, r}; // 统计通水区间
}
}
sort(a, a + cnt);
// 区间合并
int st = -1, ed = -1;
for (int i = 0; i < cnt; i++) {
if (a[i].first <= ed + 1) ed = max(ed, a[i].second);
else st = a[i].first, ed = a[i].second;
}
return st == 1 && ed == len;
}
int main() {
scanf("%d%d", &n, &len);
for (int i = 1; i <= n; i++) scanf("%d%d", &L[i], &S[i]);
int l = 0, r = 2e9;
while (l < r) {
int mid = (LL) l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
printf("%d\n", r);
return 0;
}
3.[AcWing4656.技能升级]
小蓝最近正在玩一款
他的角色一共有
其中第
现在小蓝可以总计升级
请你计算小蓝最多可以提高多少点攻击力?
输入格式
输入第一行包含两个整数
以下
输出格式
输出一行包含一个整数表示答案。
数据范围
对于
对于
对于所有评测用例,
输入样例
3 6
10 5
9 2
8 1
输出样例
47
解题思路
最简单的思路,想要攻击力总和最大,将所有技能的攻击力预处理出来利用大根堆,每次都取最大的那一个。
那么如何优化?
可以二分第
C++代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
typedef long long LL;
int n, m;
int a[N], b[N];
bool check(int mid) { // 二分攻击力
LL cnt = 0;
for (int i = 1; i <= n; i++)
if (a[i] >= mid) // 可以进行技能加点
cnt += (a[i] - mid) / b[i] + 1; // 加点次数
return cnt >= m;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d%d", &a[i], &b[i]);
int l = 0, r = 1e6;
while (l < r) {
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
LL sum = 0, cnt = 0;
for (int i = 1; i <= n; i++) {
if (a[i] >= r) {
int c = (a[i] - r) / b[i] + 1;
int ed = a[i] - (c - 1) * b[i];
cnt += c;
// 等差数列求和
sum += (LL) (a[i] + ed) * c / 2;
}
}
// 减去可能多加的攻击力
printf("%lld\n", sum - (cnt - m) * r);
return 0;
}
4.[AcWing102.最佳牛围栏]
题目描述
农夫约翰的农场由
约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。
围起区域内至少需要包含
在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。
输入格式
第一行输入整数
接下来
输出格式
输出一个整数,表示平均值的最大值乘以
数据范围
输入样例
10 6
6
4
2
10
3
8
5
9
4
1
输出样例
6500
解题思路
二分平均值。
C++代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, f;
int a[N];
double s[N];
bool check(double mid) {
for (int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i] - mid; // 减去平均值求前缀和
double minv = 0;
for (int i = 0, j = f; j <= n; i++, j++) {
minv = min(minv, s[i]);
// 区间的值大于等于 0
if (s[j] >= minv) return true;
}
return false;
}
int main() {
scanf("%d%d", &n, &f);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
double l = 0, r = 2000;
while (r - l > 1e-6) {
double mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
printf("%d\n", (int) (r * 1000));
return 0;
}
本文来自博客园,作者:Cocoicobird,转载请注明原文链接:https://www.cnblogs.com/Cocoicobird/p/18049141
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2023-03-02 数据结构1.1-单调栈