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

题目:最佳牛围栏

题目链接: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;
}
相关推荐
Miraitowa_cheems16 小时前
LeetCode算法日记 - Day 64: 岛屿的最大面积、被围绕的区域
java·算法·leetcode·决策树·职场和发展·深度优先·推荐算法
_不会dp不改名_17 小时前
leetcode_1382 将二叉搜索树变平衡树
算法·leetcode·职场和发展
旭意20 小时前
C++微基础备战蓝桥杯之数组篇10.1
开发语言·c++·蓝桥杯
墨染点香2 天前
LeetCode 刷题【103. 二叉树的锯齿形层序遍历、104. 二叉树的最大深度、105. 从前序与中序遍历序列构造二叉树】
算法·leetcode·职场和发展
旭意2 天前
C++微基础备战蓝桥杯string篇10.5
开发语言·c++·蓝桥杯
黑色的山岗在沉睡2 天前
LeetCode 2761. 和等于目标值的质数对
算法·leetcode·职场和发展
T1an-12 天前
力扣70.爬楼梯
算法·leetcode·职场和发展
我命由我123452 天前
Photoshop - Photoshop 工具栏(5)多边套索工具
笔记·学习·ui·职场和发展·photoshop·ps·美工
共享家95272 天前
Leetcode刷题
算法·leetcode·职场和发展
kalvin_y_liu2 天前
【MES架构师与C#高级工程师(设备控制方向)两大职业路径的技术】
开发语言·职场和发展·c#·mes