洛谷 #1471. 方差

版权声明:转载请注明出处 https://blog.csdn.net/qq_41593522/article/details/83993898

题意

维护区间平均数,方差

题解

平均数好弄

把方差公式展开,发现只要维护区间平方和即可

然后线段树

调试记录

手贱,把k打成l

#include <cstdio>
#define maxn 100005

using namespace std;

struct Tree{
	struct node{
		int l, r;
		double key, lazy, sqr;
	}a[maxn << 2];
	double val[maxn];
	
	void build(int cur, int l, int r){
		a[cur].l = l, a[cur].r = r; a[cur].lazy = 0; a[cur].sqr = 0;
		if (l == r){
			a[cur].key = val[l];
			a[cur].sqr = val[l] * val[l];
			return;
		}
		int mid = (l + r) >> 1;
		build(cur << 1, l, mid);
		build(cur << 1 | 1, mid + 1, r);
		a[cur].key = a[cur << 1].key + a[cur << 1 | 1].key;
		a[cur].sqr = a[cur << 1].sqr + a[cur << 1 | 1].sqr;
	}
	
	void pushdown(int cur){
		if (a[cur].lazy == 0) return;
		a[cur << 1].lazy += a[cur].lazy;
		a[cur << 1 | 1].lazy += a[cur].lazy;
		a[cur << 1].sqr += 2 * a[cur].lazy * a[cur << 1].key + (a[cur << 1].r - a[cur << 1].l + 1) * a[cur].lazy * a[cur].lazy;
		a[cur << 1 | 1].sqr += 2 * a[cur].lazy * a[cur << 1 | 1].key + (a[cur << 1 | 1].r - a[cur << 1 | 1].l + 1) * a[cur].lazy * a[cur].lazy;
		a[cur << 1].key += a[cur].lazy * (a[cur << 1].r - a[cur << 1].l + 1);
		a[cur << 1 | 1].key += a[cur].lazy * (a[cur << 1 | 1].r - a[cur << 1 | 1].l + 1);
		a[cur].lazy = 0;
	}
	
	void update(int cur, int l, int r, double k){
		if (a[cur].l > r || a[cur].r < l) return;
		if (a[cur].l >= l && a[cur].r <= r){
			a[cur].lazy += k;
			a[cur].sqr += 2 * k * a[cur].key + (a[cur].r - a[cur].l + 1) * k * k;
			a[cur].key += (a[cur].r - a[cur].l + 1) * k;
			return;
		}
		pushdown(cur);
		update(cur << 1, l, r, k); update(cur << 1 | 1, l, r, k);
		a[cur].key = a[cur << 1].key + a[cur << 1 | 1].key;
		a[cur].sqr = a[cur << 1].sqr + a[cur << 1 | 1].sqr;
	}
	
	double Query(int cur, int l, int r){
		if (a[cur].l > r || a[cur].r < l) return 0;
		if (a[cur].l >= l && a[cur].r <= r) return a[cur].key;
		pushdown(cur);
		return Query(cur << 1, l, r) + Query(cur << 1 | 1, l, r);
	}
	
	double Query_sqr(int cur, int l, int r){
		if (a[cur].l > r || a[cur].r < l) return 0;
		if (a[cur].l >= l && a[cur].r <= r) return a[cur].sqr;
		pushdown(cur);
		return Query_sqr(cur << 1, l, r) + Query_sqr(cur << 1 | 1, l, r);
	}
}t;

int n, Q;
int main(){
	scanf("%d%d", &n, &Q);
	for (int i = 1; i <= n; i++) scanf("%lf", &t.val[i]);
	t.build(1, 1, n);
	int opt, x, y;
	double z;
	while (Q--){
		scanf("%d%d%d", &opt, &x, &y);
		if (opt == 1){
			scanf("%lf", &z); t.update(1, x, y, z);
		}
		if (opt == 2){
			printf("%.4lf\n", t.Query(1, x, y) / (y - x + 1));
		}
		if (opt == 3){
			double avr = 1.0 * t.Query(1, x, y) / (y - x + 1);
			printf("%.4lf\n", (t.Query_sqr(1, x, y) - 2 * avr * t.Query(1, x, y) + (y - x + 1) * avr * avr) / (y - x + 1));
		}
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41593522/article/details/83993898