题目大意:
成为一个神后,最大的责任便是保护神界的人民,他们都出生在神界,但并不都具有神的实力。当然,神界人族的内部也有战争,他们一共分为N个部落,每两个部落之间都有可能发生战争。为了不然神界人族因为战争而损失惨重,神界的诸神将这些部落编号为1 ~ N,当这些部落的人数差距太大时,诸神便会降临,将一些部落的人带走,并放一些在别的部落中。而衡量所有部落人数差距的数值便是方差。接下来,Ta会告诉你一些部落的人数增加或减少的信息,并会不时的询问你编号为L~R的部落的总人数或是他们部落人数的方差。
解题思路:
数据范围是
n
≤
100000
n\leq 100000
n≤100000所以我们可以用线段树(分块)分别维护区间平方和及区间和,然后回答即可。
A c c e p t e d c o d e Accepted\ code Accepted code:
#include<cstdio>
using namespace std;
struct node{
long long l, r, sum, add, ft;
}tree[400001];
int n, q;
int a[100001];
void build(int p, int l, int r) {
tree[p].l = l;
tree[p].r = r;
if (l == r) {
tree[p].sum = a[l];
tree[p].ft = a[l] * a[l];
return;
}
int mid = l + r >> 1;
build(p<<1, l, mid);
build(p<<1|1, mid + 1, r);
tree[p].sum = tree[p<<1].sum + tree[p<<1|1].sum;
tree[p].ft = tree[p<<1].ft + tree[p<<1|1].ft;
}
void spread(int p) {
if (tree[p].add) {
tree[p<<1].add += tree[p].add;
tree[p<<1|1].add += tree[p].add;
tree[p<<1].ft += 2 * tree[p<<1].sum * tree[p].add + (tree[p<<1].r - tree[p<<1].l + 1) * tree[p].add * tree[p].add;
tree[p<<1|1].ft += 2 * tree[p<<1|1].sum * tree[p].add + (tree[p<<1|1].r - tree[p<<1|1].l + 1) * tree[p].add * tree[p].add;
tree[p<<1].sum += tree[p].add * (tree[p<<1].r - tree[p<<1].l + 1);
tree[p<<1|1].sum += tree[p].add * (tree[p<<1|1].r - tree[p<<1|1].l + 1);
tree[p].add = 0;
}
}
void change(int p, int l, int r, int v) {
if (l <= tree[p].l && tree[p].r <= r) {
tree[p].ft += (tree[p].sum * v << 1) + (tree[p].r - tree[p].l + 1) * v * v;
tree[p].sum += v * (tree[p].r - tree[p].l + 1);
tree[p].add += v;
return;
}
spread(p);
int ft = (tree[p].l + tree[p].r) / 2;
if (l <= ft) change(p<<1, l, r, v);
if (r > ft) change(p<<1|1, l, r, v);
tree[p].sum = tree[p<<1].sum + tree[p<<1|1].sum;
tree[p].ft = tree[p<<1].ft + tree[p<<1|1].ft;
}
long long ask(int p, int l, int r) {
if (l <= tree[p].l && tree[p].r <= r)
return tree[p].sum;
spread(p);
int ft = (tree[p].l + tree[p].r) / 2;
long long solve = 0;
if (l <= ft) solve += ask(p<<1, l, r);
if (r > ft) solve += ask(p<<1|1, l, r);
return solve;
}
long long ask_(int p, int l, int r) {
if (l <= tree[p].l && tree[p].r <= r)
return tree[p].ft;
spread(p);
int ft = (tree[p].l + tree[p].r) >> 1;
long long solve = 0;
if (l <= ft) solve += ask_(p<<1, l, r);
if (r > ft) solve += ask_(p<<1|1, l, r);
return solve;
}
signed main() {
scanf("%d %d", &n, &q);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, 1, n);
int op = 0, x = 0, y = 0, z = 0;
while (q--) {
scanf("%d", &op);
if (op == 0) {
scanf("%d %d", &x, &y);
change(1, x, x, y);
} else if (op == 1) {
scanf("%d %d %d", &x, &y, &z);
change(1, x, y, z);
} else if (op == 2) {
scanf("%d %d", &x, &y);
printf("%d\n", ask(1, x, y));
} else if (op == 3) {
scanf("%d %d", &x, &y);
long long s1 = ask_(1, x, y), s2 = ask(1, x, y);
double pjs = (double)s2 / (y - x + 1), s3 = s1 - 2 * s2 * pjs + (y - x + 1) * pjs * pjs;
printf("%.10lf\n", s3 / (y - x + 1));
}
}
}