蓝桥杯备赛之二分专题

2024-03-08 09:12
文章标签 二分 蓝桥 专题 杯备赛

本文主要是介绍蓝桥杯备赛之二分专题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

常用的算法二分模板

1. 在数组a[]中找大于等于x的第一个数的下标

//int ans = lower_bound(a, a + n, x) - a
//相当于下方
int l = 0, r = n - 1;
while(l < r) {int mid = l + r >> 1;if(a[mid] >= x)	r = mid;else l = mid + 1;
}
cout << r;

2. 在数组a[]中找大于x的第一个数的下标

//int ans = upper_bound(a, a + n, x) - a
//相当于下方
int l = 0, r = n - 1;
while(l < r) {int mid = l + r + 1 >> 1;if(a[mid] <= x) l = mid;else r = mid + 1;
}
cout << r;

例题

503.借教室

题目

在这里插入图片描述

在这里插入图片描述

思路

二分_借教室.png

代码
//根据题意:有单调性,区间操作  二分+差分
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int r[N], d[N], s[N], t[N];
LL b[N];    //差分数组
int n, m;
bool check(int mid) {for(int i = 1; i <= n; i++) b[i] = r[i] - r[i - 1]; //初始化差分数组for(int i = 1; i <= mid; i++) {b[s[i]] -= d[i];b[t[i] + 1] += d[i];}for(int i = 1; i <= n; i++ ) {b[i] += b[i - 1];if(b[i] < 0)    return true;}return false;
}
int main() {scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) scanf("%d", &r[i]);for(int i = 1; i <= m; i++) scanf("%d%d%d", &d[i], &s[i], &t[i]);int l = 1, r = m;if(!check(m)) {puts("0");return 0;}while(l < r) {int mid = l + r >> 1;if(check(mid))  r = mid;else l = mid + 1;}printf("-1\n%d", r);return 0;
}

5407.管道

题目

在这里插入图片描述

代码
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
typedef long long LL;
int n, len;
int l[N], s[N];
pair<int, int> q[N];
bool check(LL mid) {    //mid为当前时间int cnt = 0;for(int i = 1; i <= n; i++) {if(s[i] <= mid)  {// q[cnt++] = {mid - s[i], mid + s[i]};    别忘了区间长度限制int d = mid - s[i];LL L = max(1, l[i] - d), R = min((LL)len, (LL)l[i] + d);q[cnt++] = {L, R};}}sort(q, q + cnt);int st = -1, ed = -1;for(int i = 0; i < cnt; i++) {//这里是 ed+1 因为需要的是每个节点有水,相当于“相连”if(q[i].first <= ed + 1)    ed = max(ed, q[i].second);else {st = q[i].first, ed = q[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]);LL l = 0, r = 2e9;      //最坏情况是2e9while(l < r) {LL mid = l + r >> 1;if(check(mid))  r = mid;else l = mid + 1;}cout << r;return 0;
}

(多路合并)

1262.鱼塘钓鱼

在这里插入图片描述

思路

在这里插入图片描述

枚举最后一次钓鱼的鱼塘, 传入参数(第k个鱼塘, 钓鱼时间)

代码如下
#include <iostream>
#include <cstring>
using namespace std;
const int N = 110;
int T, n;
int s[N], d[N], t[N], spend[N];  
int get_fish(int k) {   //在第k个鱼塘当前能钓鱼数量return max(0, s[k] - spend[k] * d[k]);
}
int work(int n, int T) {int res = 0;memset(spend, 0, sizeof spend);for(int i = 0; i < T; i++) {    //一共枚举T次,T分钟则可选择钓T次int t = 1;  //循环判断哪个鱼塘当前能钓鱼数最多for(int j = 2; j <= n; j++)if(get_fish(j) > get_fish(t))t = j;res += get_fish(t);  //答案加上此时钓鱼数量spend[t]++;     //当前鱼塘钓鱼时间++}return res;
}
int main () {scanf("%d", &n);for(int i = 1; i <= n; i++)  scanf("%d", &s[i]);for(int i = 1; i <= n; i++)  scanf("%d", &d[i]);    //走到第一个鱼塘不用时间for(int i = 2; i <= n; i++) cin >> t[i], t[i] += t[i - 1];cin >> T;int res = 0;// 枚举最后走到哪个鱼塘for(int i = 1; i <= n; i++) res = max(res, work(i, T - t[i]));  //最后走到第i个鱼塘,钓鱼时间为T-t[i]cout << res;return 0;
}
4656.技能升级
题目:

在这里插入图片描述

思路分析:

在这里插入图片描述

在这里插入图片描述

代码和注释具体如下
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 100010;
int n, m;
int a[N], b[N];
bool check(int mid) {LL res = 0;for(int i = 0; i < n; i++)if(a[i] >= mid)res += (a[i] - mid) / b[i] + 1; //对于第i个技能所加的次数 :差值 / 公差 + 1,因为差值为0时,还需要加一次if(res >= m)  return true;    //判断对于最后一次为mid值所对应加技能的总次数是否满足要求m次return false;
}
int main() {scanf("%d%d", &n, &m);//m 的范围太大, 故从n下手,也就是枚举加的技能点值,二分答案for(int i = 0; i < n; i++)  scanf("%d%d", &a[i], &b[i]);int l = 0, r = 1e6;     //左右边界(最后一次(m)加的技能点)while(l < r) {// l 和 r 的更新,***关键***//这里的话由于所加技能点是从大到小排序进行选择的,故答案必然是[mid,...]的区间(mid对应的值可能不止一个),而小于mid的不符合int mid = l + r + 1 >> 1;if(check(mid))  l = mid;else r = mid - 1;}LL res = 0, cnt = 0;    //次数,答案for(int i = 0; i < n; i++) {if(a[i] > r) {  // r 即为最后一次加的技能点数int s = (a[i] - r) / b[i] + 1;  //第i个技能所加次数int an = a[i] - (s - 1) * b[i]; //最后一次升级的点数res += (LL)(a[i] + an) * s / 2;     //等差数列公式求出所加技能点和cnt += s;   //累加加技能次数}}LL ans = res - (cnt - m) * r;   //最后一个数值可能加的次数不止一次,故需要特殊处理cout << ans;return 0;
}

这篇关于蓝桥杯备赛之二分专题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/786632

相关文章

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu2289(简单二分)

虽说是简单二分,但是我还是wa死了  题意:已知圆台的体积,求高度 首先要知道圆台体积怎么求:设上下底的半径分别为r1,r2,高为h,V = PI*(r1*r1+r1*r2+r2*r2)*h/3 然后以h进行二分 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#includ

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

poj 3104 二分答案

题意: n件湿度为num的衣服,每秒钟自己可以蒸发掉1个湿度。 然而如果使用了暖炉,每秒可以烧掉k个湿度,但不计算蒸发了。 现在问这么多的衣服,怎么烧事件最短。 解析: 二分答案咯。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <c

poj 3258 二分最小值最大

题意: 有一些石头排成一条线,第一个和最后一个不能去掉。 其余的共可以去掉m块,要使去掉后石头间距的最小值最大。 解析: 二分石头,最小值最大。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <c

poj 2594 二分图最大独立集

题意: 求一张图的最大独立集,这题不同的地方在于,间接相邻的点也可以有一条边,所以用floyd来把间接相邻的边也连起来。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <sta

poj 3692 二分图最大独立集

题意: 幼儿园里,有G个女生和B个男生。 他们中间有女生和女生认识,男生男生认识,也有男生和女生认识的。 现在要选出一些人,使得这里面的人都认识,问最多能选多少人。 解析: 反过来建边,将不认识的男生和女生相连,然后求一个二分图的最大独立集就行了。 下图很直观: 点击打开链接 原图: 现图: 、 代码: #pragma comment(

poj 2112 网络流+二分

题意: k台挤奶机,c头牛,每台挤奶机可以挤m头牛。 现在给出每只牛到挤奶机的距离矩阵,求最小化牛的最大路程。 解析: 最大值最小化,最小值最大化,用二分来做。 先求出两点之间的最短距离。 然后二分匹配牛到挤奶机的最大路程,匹配中的判断是在这个最大路程下,是否牛的数量达到c只。 如何求牛的数量呢,用网络流来做。 从源点到牛引一条容量为1的边,然后挤奶机到汇点引一条容量为m的边

二分最大匹配总结

HDU 2444  黑白染色 ,二分图判定 const int maxn = 208 ;vector<int> g[maxn] ;int n ;bool vis[maxn] ;int match[maxn] ;;int color[maxn] ;int setcolor(int u , int c){color[u] = c ;for(vector<int>::iter