Robert 的军队(结论)(数学)

168 篇文章 0 订阅
47 篇文章 2 订阅

Robert 的军队

题目大意

给你一个数组,要你选 l~r 个数,使得这些数的方差最小。

思路

首先我们不难想到把人丢去排序,然后因为方差嘛,我们肯定选的是一段连续的区间。
我们要搞出一个结论,就是如果你选好了一个区间,你在旁边再选一个数扩大它,它的方差不会减小,只会不变或变大。

那我们就可以得出一个结论,就是最优你选的数的长度一定是 l l l
然后就很简单了,枚举每个位置,找到对应长度为 l l l 的,然后算。
当然不能一个一个枚举,肯定是要化一下式子加速算方差的过程的。
x ‾ = ∑ i = 1 n a i n \overline{x}=\frac{\sum\limits_{i=1}^na_i}{n} x=ni=1nai

s 2 = ∑ i = 1 n ( a i − x ‾ ) 2 n s^2=\dfrac{\sum\limits_{i=1}^n(a_i-\overline{x})^2}{n} s2=ni=1n(aix)2
= ∑ i = 1 n ( a i 2 − 2 a i x ‾ ) + n x ‾ 2 n =\dfrac{\sum\limits_{i=1}^n(a_i^2-2a_i\overline{x})+n\overline{x}^2}{n} =ni=1n(ai22aix)+nx2
= ∑ i = 1 n a i 2 − 2 n x ‾ 2 + n x ‾ 2 n =\dfrac{\sum\limits_{i=1}^na_i^2-2n\overline{x}^2+n\overline{x}^2}{n} =ni=1nai22nx2+nx2
= ∑ i = 1 n a i 2 − n x ‾ 2 n =\dfrac{\sum\limits_{i=1}^na_i^2-n\overline{x}^2}{n} =ni=1nai2nx2
= ∑ i = 1 n a i 2 n − x ‾ 2 =\dfrac{\sum\limits_{i=1}^na_i^2}{n}-\overline{x}^2 =ni=1nai2x2
= ∑ i = 1 n a i 2 n − ( ∑ i = 1 n a i ) 2 n 2 =\dfrac{\sum\limits_{i=1}^na_i^2}{n}-\dfrac{(\sum\limits_{i=1}^na_i)^2}{n^2} =ni=1nai2n2(i=1nai)2

然后每次你往右移,新多的一个数,少了一个数,可以直接快四维护左边上面部分,然后右边上面部分就是直接预处理前缀和然后就可以直接得到。
然后除了下面减了就可以得到了。

代码

#include<cstdio>
#include<algorithm>
#define ll long long

using namespace std;

const int N = 100005;
int n, l, r, h[N];
double ans, x, y, sum[N];

int main() {
//	freopen("army.in", "r", stdin);
//	freopen("army.out", "w", stdout);
	
	scanf("%d %d %d", &n, &l, &r);
	for (int i = 1; i <= n; i++) scanf("%d", &h[i]);
	
	sort(h + 1, h + n + 1);
	for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + h[i];
	ans = 100000000000000000000000000.0;
	for (int i = 1; i <= n; i++) {
		int j = max(1, i - l + 1);
		x += 1.0 * h[i] * h[i];
		if (i >= l) {
			y = 1.0 * (sum[i] - sum[j - 1]) * (sum[i] - sum[j - 1]);//维护方差的两个值
			ans = min(ans, 1.0 * x / (1.0 * (i - j + 1)) - 1.0 * y / (1.0 * (i - j + 1)) / (1.0 * (i - j + 1)));//求出方差,取最小的
			x -= 1.0 * h[j] * h[j];
		}
	}
	
	printf("%.3lf", ans);
	
	fclose(stdin);
	fclose(stdout);
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值