题意:从城市1到城市n,每相邻编号城市之间有一条道路,初始过路费用都为0,然后有两种操作,change a b c表示城市a到城市b之间的所有道路费用加c,establish a b表示在城市a到城市b区间内任意选一个城市为起点,选一个城市为终点,输出从起点到终点通过道路的平均费用。
题解:对于每一条道路假设起点为k终点为k+1,如果知道了左右区间l r,就可以知道这条路走(k-l+1)×(r-k)次从而计算总费用,展开后就是cost[k]×(-k^2+(l+r-1)k + (r-(1-l))),只需要在线段树内维护cost[k]×k^2和cost[k]×k和cost[k]。
#include <cstdio>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;
const int N = 100005;
int n, m, id;
ll A[N][3], p[3][N << 2], sum[3][N << 2], addv[3][N << 2];
char op[30];
void pushup(int k) {
sum[id][k] = sum[id][k * 2] + sum[id][k * 2 + 1];
}
void pushdown(int k) {
if (addv[id][k]) {
addv[id][k * 2] += addv[id][k];
addv[id][k * 2 + 1] += addv[id][k];
sum[id][k * 2] += addv[id][k] * p[id][k * 2];
sum[id][k * 2 + 1] += addv[id][k] * p[id][k * 2 + 1];
addv[id][k] = 0;
}
}
void build(int k, int left, int right) {
p[id][k] = sum[id][k] = addv[id][k] = 0;
if (left == right) {
p[id][k] = A[left][id];
return;
}
int mid = (left + right) / 2;
build(k * 2, left, mid);
build(k * 2 + 1, mid + 1, right);
p[id][k] = p[id][k * 2] + p[id][k * 2 + 1];
}
void modify(int k, int left, int right, int l, int r, ll x) {
if (l <= left && right <= r) {
addv[id][k] += x;
sum[id][k] += x * p[id][k];
return;
}
pushdown(k);
int mid = (left + right) / 2;
if (l <= mid)
modify(k * 2, left, mid, l, r, x);
if (r > mid)
modify(k * 2 + 1, mid + 1, right, l, r, x);
pushup(k);
}
ll query(int k, int left, int right, int l, int r) {
if (l <= left && right <= r) {
return sum[id][k];
}
pushdown(k);
int mid = (left + right) / 2;
ll temp = 0;
if (l <= mid)
temp += query(k * 2, left, mid, l, r);
if (r > mid)
temp += query(k * 2 + 1, mid + 1, right, l, r);
pushup(k);
return temp;
}
int main() {
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = 1; i <= n; i++) {
A[i][0] = 1;
A[i][1] = (ll)i;
A[i][2] = (ll)i * (ll)i;
}
n--;
for (int i = 0; i < 3; i++) {
id = i;
build(1, 1, n);
}
int l, r;
while (m--) {
scanf("%s%d%d", op, &l, &r);
if (op[0] == 'c') {
ll x;
scanf("%lld", &x);
for (int i = 0; i < 3; i++) {
id = i;
modify(1, 1, n, l, r - 1, x);
}
}
else {
id = 2;
ll a = query(1, 1, n, l, r - 1);
id = 1;
ll b = query(1, 1, n, l, r - 1);
id = 0;
ll c = query(1, 1, n, l, r - 1);
double res = -a + b * (l + r - 1) + c * r * (1 - l);
printf("%.8lf\n", res * 2 / (r - l + 1) / (r - l));
}
}
}
return 0;
}