P1419 寻找段落

题目描述

给定一个长度为 n 的序列 a,定义ai​ 为第 i 个元素的价值。现在需要找出序列中最有价值的“段落”。段落的定义是长度在 [S, T] 之间的连续序列。最有价值段落是指平均值最大的段落。

段落的平均值 等于 段落总价值 除以 段落长度

输入格式

第一行一个整数 n,表示序列长度。

第二行两个整数 S 和 T,表示段落长度的范围,在 [S,T] 之间。

第三行到第 n+2 行,每行一个整数表示每个元素的价值指数。

输出格式

一个实数,保留 3 位小数,表示最优段落的平均值。

思路:单调队列+二分法

单调队列是单调递减的在 s~t区间内,有平均数mid是为true;

用i - s遍历数组的i- s个数,在区间s~ t中找到最小的值即可。当满足s时就可以判断t,t是可以遍历数组满足s是区间不超过 t 是的数组区间

在队列中最多有 t 个元素 , i - t是保证元素在s~t之间的

#include<iostream>
#include<string>
#include<algorithm>
#include<deque>
using namespace std;
int n, s, t;
double a[100010], sum[100010];
int check(double mid) {
	sum[0] = 0;
	for (int i = 1; i <= n; i++)
		sum[i] = sum[i - 1] + a[i] - mid; 
	deque<int> q;
	for (int i = 1; i <= n; i++) {
		if (i >= s) {
			while (!q.empty() && sum[i - s] < sum[q.back()]) q.pop_back();
			q.push_back(i - s);
		}
		if (!q.empty() && q.front() < i - t) q.pop_front();
		if (!q.empty() && sum[i] - sum[q.front()] >= 0) return 1;
	}
	return 0;
}
int main() {
	cin >> n >> s >> t;
	double m1 = 0x3f3f3f, m2 = -0x3f3f3f;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		if(m1 > a[i])
		m1 =  a[i];
		if(m2 <a[i])
		m2 =  a[i];
	}
	double l = m1, r = m2;
	while (r - l > 1e-5) {
		double mid = (l + r) / 2;
		if (check(mid)) l = mid;
		else r = mid; // 平均数
	}
	printf("%.3lf\n", l);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值