题意
给出一个序列,有几个操作:
操作1:1 x y k ,表示将第x到第y项每项加上k,k为一实数。
操作2:2 x y ,表示求出第x到第y项这一子数列的平均数。
操作3:3 x y ,表示求出第x到第y项这一子数列的方差。
思路
做法与寻找神格类似,这里就不多说了。
代码
#include<cstdio>
struct node{
int l, r;
double sum, add, pfh;
}tree[400001];
int n, q;
double a[100001];
long long input() {
char c = getchar();
int f = 1;
long long result = 0;
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
result = result * 10 + (c - 48);
c = getchar();
}
return result * f;
}
void print(long long x) {
if (x < 0) putchar(45), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + 48);
}
void println(long long x) {
print(x);
putchar(10);
}
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].pfh = a[l] * a[l];
return;
}
int mid = (l + r) / 2;
build(p * 2, l, mid);
build(p * 2 + 1, mid + 1, r);
tree[p].sum = tree[p * 2].sum + tree[p * 2 + 1].sum;
tree[p].pfh = tree[p * 2].pfh + tree[p * 2 + 1].pfh;
}
void spread(int p) {
if (tree[p].add) {
tree[p * 2].add += tree[p].add;
tree[p * 2 + 1].add += tree[p].add;
tree[p * 2].pfh += 2 * tree[p * 2].sum * tree[p].add + (tree[p * 2].r - tree[p * 2].l + 1) * tree[p].add * tree[p].add;
tree[p * 2 + 1].pfh += 2 * tree[p * 2 + 1].sum * tree[p].add + (tree[p * 2 + 1].r - tree[p * 2 + 1].l + 1) * tree[p].add * tree[p].add;
tree[p * 2].sum += tree[p].add * (tree[p * 2].r - tree[p * 2].l + 1);
tree[p * 2 + 1].sum += tree[p].add * (tree[p * 2 + 1].r - tree[p * 2 + 1].l + 1);
tree[p].add = 0;
}
}
void change(int p, int l, int r, double v) {
if (l <= tree[p].l && tree[p].r <= r) {
tree[p].pfh += 2 * tree[p].sum * v + (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 mid = (tree[p].l + tree[p].r) / 2;
if (l <= mid) change(p * 2, l, r, v);
if (r > mid) change(p * 2 + 1, l, r, v);
tree[p].sum = tree[p * 2].sum + tree[p * 2 + 1].sum;
tree[p].pfh = tree[p * 2].pfh + tree[p * 2 + 1].pfh;
}
double ask(int p, int l, int r) {
if (l <= tree[p].l && tree[p].r <= r)
return tree[p].sum;
spread(p);
int mid = (tree[p].l + tree[p].r) / 2;
double result = 0;
if (l <= mid) result += ask(p * 2, l, r);
if (r > mid) result += ask(p * 2 + 1, l, r);
return result;
}
double askpfh(int p, int l, int r) {
if (l <= tree[p].l && tree[p].r <= r)
return tree[p].pfh;
spread(p);
int mid = (tree[p].l + tree[p].r) / 2;
double result = 0;
if (l <= mid) result += askpfh(p * 2, l, r);
if (r > mid) result += askpfh(p * 2 + 1, l, r);
return result;
}
int main() {
n = input();
q = input();
for (int i = 1; i <= n; i++)
scanf("%lf", &a[i]);
build(1, 1, n);
int op, x, y;
double z;
for (; q; q--) {
op = input();
if (op == 1) {
x = input();
y = input();
scanf("%lf", &z);
change(1, x, y, z);
} else if (op == 2) {
x = input();
y = input();
printf("%.4lf\n", ask(1, x, y) / (y - x + 1));
} else if (op == 3) {
x = input();
y = input();
double s1 = askpfh(1, x, y), s2 = ask(1, x, y);
double pjs = (double)s2 / (y - x + 1);
double s3 = s1 - 2 * s2 * pjs + (y - x + 1) * pjs * pjs;
printf("%.4lf\n", s3 / (y - x + 1));
}
}
}