蓝桥杯复习之二分法与前缀和

题目:最佳牛围栏

题目链接:https://www.acwing.com/problem/content/104/

题意:农夫约翰的农场由 N 块田地组成,每块地里都有一定数量的牛,其数量不会少于 1 头,也不会超过 2000 头。

约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。

围起区域内至少需要包含 F 块地,其中 F 会在输入中给出。

在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少?

思路:

找平均值/最小(大)值的最大(小)值,往二分答案方向想,二分答案的模板见代码。我们在每一次假设答案的计算过程中,将数组都减去mid方便计算(也就是只要存在满足条件同时大于0的字段就可以返回true了)

因为是找连续的一段,我们用前缀和优化计算,假设前缀和数组为pre,只要存在pre[j]-pre[i]>=0且j-i>=f就可以返回true了。

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

using ll = long long;
const ll N = 100005;
const ll mod = 1e9 + 7;
const int maxn = 2005;
int gcd(int a, int b) {
	return b ? gcd(b, a % b) : a;
}

int n, f;
int a[N];
double pre[N];

bool check(double m) {
	for (int i = 1; i <= n; i++) {
		pre[i] = pre[i - 1] + a[i] * 1.0 - m;
	}
	
	double minn = 0;

	for (int i = 0, j = f; j <= n; j++, i++) {
		minn = min(minn, pre[i]);
		if (pre[j] >= minn)
			return true;
	}
	return false;
}

void solve() {
	cin >> n >> f;

	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}

	double l = 1, r = 2002;
	while (r-l>=1e-5) {
		double mid = (l + r) / 2;
		if (check(mid)) {
			l = mid;
		}
		else
			r = mid;
	}
	cout << (int)(r * 1000) << '\n';

}
		

signed main() {

	ios::sync_with_stdio(false);
	cin.tie(0);
	std::cout.tie(0);

	int t = 1; //cin >> t;
	while (t--)
		solve();

	return 0;
}
相关推荐
熬了夜的程序员1 天前
【LeetCode】89. 格雷编码
算法·leetcode·链表·职场和发展·矩阵
程序员杰哥1 天前
Pytest之收集用例规则与运行指定用例
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·pytest
熬了夜的程序员1 天前
【LeetCode】87. 扰乱字符串
算法·leetcode·职场和发展·排序算法
超级大只老咪1 天前
蓝桥杯知识点大纲(JavaC组)
java·算法·蓝桥杯
遇印记2 天前
2026蓝桥杯
职场和发展·蓝桥杯
熬了夜的程序员2 天前
【LeetCode】88. 合并两个有序数组
数据结构·算法·leetcode·职场和发展·深度优先
尘觉2 天前
面试-浅复制和深复制?怎样实现深复制详细解答
javascript·面试·职场和发展
007php0072 天前
京东面试题解析:同步方法、线程池、Spring、Dubbo、消息队列、Redis等
开发语言·后端·百度·面试·职场和发展·架构·1024程序员节