很明显是要推公式啊,然后用线段树维护。
以下我们将
∑
i
=
l
r
\sum_{i=l}^r
∑i=lr看成
∑
\sum
∑
把操作1的公式化简一下,就可以得到需要维护的有
∑
x
i
\sum x_i
∑xi
∑ y i \sum y_i ∑yi
∑ x i ∗ y i \sum x_i*y_i ∑xi∗yi
∑ x i 2 \sum x_i^2 ∑xi2
这四种。
然后用上求和公式和平方和公式就可以很容易的得到操作二和操作三分别是:
(操作二)
∑
x
i
+
=
(
r
−
l
+
1
)
∗
S
\sum x_i+=(r-l+1)*S
∑xi+=(r−l+1)∗S
∑ y i + = ( r − l + 1 ) ∗ T \sum y_i+=(r-l+1)*T ∑yi+=(r−l+1)∗T
∑ x i ∗ y i + = T ∗ ∑ x i + S ∗ ∑ y i + ( r − l + 1 ) ∗ S ∗ T \sum x_i*y_i+=T*\sum x_i+S*\sum y_i+(r-l+1)*S*T ∑xi∗yi+=T∗∑xi+S∗∑yi+(r−l+1)∗S∗T
∑ x i 2 + = 2 ∗ S ∗ ∑ x i + ( r − l + 1 ) ∗ S 2 \sum x_i^2+=2*S*\sum x_i+(r-l+1)*S^2 ∑xi2+=2∗S∗∑xi+(r−l+1)∗S2
(操作三)
∑
x
i
=
(
r
−
l
+
1
)
∗
S
+
(
r
−
l
+
1
)
(
l
+
r
)
2
\sum x_i=(r-l+1)*S+\frac{(r-l+1)(l+r)}{2}
∑xi=(r−l+1)∗S+2(r−l+1)(l+r)
∑ y i = ( r − l + 1 ) ∗ T + ( r − l + 1 ) ( l + r ) 2 \sum y_i=(r-l+1)*T+\frac{(r-l+1)(l+r)}{2} ∑yi=(r−l+1)∗T+2(r−l+1)(l+r)
∑ x i ∗ y i = ( r − l + 1 ) ∗ S ∗ T + ( S + T ) ( l + r ) ( r − l + 1 ) 2 + r ( r + 1 ) ( 2 r + 1 ) 6 − l ( l − 1 ) ( 2 l − 1 ) 6 \sum x_i*y_i=(r-l+1)*S*T+\frac{(S+T)(l+r)(r-l+1)}{2}+\frac{r(r+1)(2r+1)}{6}-\frac{l(l-1)(2l-1)}{6} ∑xi∗yi=(r−l+1)∗S∗T+2(S+T)(l+r)(r−l+1)+6r(r+1)(2r+1)−6l(l−1)(2l−1)
∑ x i 2 = ( r − l + 1 ) ∗ S 2 + S ∗ ( l + r ) ( r − l + 1 ) + r ( r + 1 ) ( 2 r + 1 ) 6 − l ( l − 1 ) ( 2 l − 1 ) 6 \sum x_i^2=(r-l+1)*S^2+S*(l+r)(r-l+1)+\frac{r(r+1)(2r+1)}{6}-\frac{l(l-1)(2l-1)}{6} ∑xi2=(r−l+1)∗S2+S∗(l+r)(r−l+1)+6r(r+1)(2r+1)−6l(l−1)(2l−1)
参考代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
inline int read() {
int x = 0, f = 0; char s = getchar();
while (!isdigit(s)) f |= s=='-', s = getchar();
while ( isdigit(s)) x = x * 10 + s - 48, s = getchar();
return f ? -x : x;
}
const int N = 1e5 + 5, M = 4e5 + 5;
int n, m, X[N], Y[N], QAQ = 1;
struct cyx {
double sumX, sumY, sumXY, sumX2, addX, addY,
firX, firY; bool cn;
int l, r, lc, rc;
} t[M];
struct clb {
double sumX, sumY, sumXY, sumX2;
friend inline clb operator + (clb a, clb b) {
clb res; res.sumX = a.sumX + b.sumX;
res.sumY = a.sumY + b.sumY;
res.sumX2 = a.sumX2 + b.sumX2;
res.sumXY = a.sumXY + b.sumXY;
return res;
}
};
inline double sqr(const double x) {return x * x;}
inline double sumx2(double l, double r) {
return 1.0 * r * (r + 1) * (2.0 * r + 1) / 6.0
- 1.0 * l * (l - 1) * (2.0 * l - 1) / 6.0;
}
inline void downdate(int x) {
int lc = t[x].lc, rc = t[x].rc;
if (t[x].cn) {
t[lc].firX = t[x].firX;
t[rc].firX = t[x].firX;
t[lc].cn = t[rc].cn = 1; t[x].cn = 0;
t[lc].addX = t[rc].addX = 0;
t[lc].firY = t[x].firY;
t[rc].firY = t[x].firY;
t[lc].cn = t[rc].cn = 1; t[x].cn = 0;
t[lc].addY = t[rc].addY = 0;
}
t[lc].addX += t[x].addX; t[rc].addX += t[x].addX; t[x].addX = 0;
t[lc].addY += t[x].addY; t[rc].addY += t[x].addY; t[x].addY = 0;
}
inline void upt(int x) {
int lc = t[x].lc, rc = t[x].rc, l = t[x].l, r = t[x].r;
double x1, y1, xy1, x21, x2, y2, xy2, x22; int mid = l + r >> 1;
x1 = t[lc].sumX; x2 = t[rc].sumX;
y1 = t[lc].sumY; y2 = t[rc].sumY;
x21 = t[lc].sumX2; x22 = t[rc].sumX2;
xy1 = t[lc].sumXY; xy2 = t[rc].sumXY;
x21 += 2.0 * x1 * t[lc].addX + t[lc].addX * t[lc].addX * (mid - l + 1);
x22 += 2.0 * x2 * t[rc].addX + t[rc].addX * t[rc].addX * (r - mid);
xy1 += x1 * t[lc].addY + t[lc].addX * y1 + t[lc].addX * t[lc].addY * (mid - l + 1);
xy2 += x2 * t[rc].addY + t[rc].addX * y2 + t[rc].addX * t[rc].addY * (r - mid);
x1 += t[lc].addX * (mid - l + 1); x2 += t[rc].addX * (r - mid);
y1 += t[lc].addY * (mid - l + 1); y2 += t[rc].addY * (r - mid);
if (t[lc].cn) {
double lx = t[lc].firX + t[lc].addX, ly = t[lc].firY + t[lc].addY;
x21 = 1.0 * (mid - l + 1) * sqr(lx) + lx * (l + mid) *
(mid - l + 1) + sumx2(l, mid);
xy1 = 1.0 * lx * ly * (mid - l + 1) + (lx + ly) * (l + mid)
* (mid - l + 1) / 2.0 + sumx2(l, mid);
x1 = lx * (mid - l + 1) + 1.0 * (l + mid) * (mid - l + 1) / 2.0;
y1 = ly * (mid - l + 1) + 1.0 * (l + mid) * (mid - l + 1) / 2.0;
}
if (t[rc].cn) {
double rx = t[rc].firX + t[rc].addX, ry = t[rc].firY + t[rc].addY;
x22 = 1.0 * (r - mid) * sqr(rx) + rx * (mid + 1 + r) *
(r - mid) + sumx2(mid + 1, r);
xy2 = 1.0 * rx * ry * (r - mid) + (rx + ry) * (mid + 1 + r)
* (r - mid) / 2.0 + sumx2(mid + 1, r);
x2 = rx * (r - mid) + 1.0 * (mid + 1 + r) * (r - mid) / 2.0;
y2 = ry * (r - mid) + 1.0 * (mid + 1 + r) * (r - mid) / 2.0;
}
t[x].sumX = x1 + x2; t[x].sumY = y1 + y2;
t[x].sumXY = xy1 + xy2; t[x].sumX2 = x21 + x22;
}
inline void build(int l, int r, int p) {
t[p].l = l; t[p].r = r;
if (l == r) {
t[p].sumX = X[l]; t[p].sumY = Y[l];
t[p].sumXY = t[p].sumX * t[p].sumY;
t[p].sumX2 = t[p].sumX * t[p].sumX;
return;
}
int p2 = (t[p].lc = ++QAQ), p3 = (t[p].rc = ++QAQ);
int mid = l + r >> 1; build(l, mid, p2); build(mid + 1, r, p3);
t[p].sumX = t[p2].sumX + t[p3].sumX;
t[p].sumY = t[p2].sumY + t[p3].sumY;
t[p].sumXY = t[p2].sumXY + t[p3].sumXY;
t[p].sumX2 = t[p2].sumX2 + t[p3].sumX2;
}
inline void change(int s, int e, int Si, int Ti, int p) {
int l = t[p].l, r = t[p].r;
if (l == s && r == e) {
t[p].addX += 1.0 * Si; t[p].addY += 1.0 * Ti;
return;
}
int mid = l + r >> 1, p2 = t[p].lc, p3 = t[p].rc; downdate(p);
if (e <= mid) change(s, e, Si, Ti, p2);
else if (s >= mid + 1) change(s, e, Si, Ti, p3);
else change(s, mid, Si, Ti, p2), change(mid + 1, e, Si, Ti, p3);
upt(p);
}
inline void modify(int s, int e, int Si, int Ti, int p) {
int l = t[p].l, r = t[p].r;
if (t[p].l == s && t[p].r == e) {
t[p].cn = 1; t[p].firX = 1.0 * Si; t[p].firY = 1.0 * Ti;
t[p].addX = t[p].addY = 0;
return;
}
int mid = l + r >> 1, p2 = t[p].lc, p3 = t[p].rc; downdate(p);
if (e <= mid) modify(s, e, Si, Ti, p2);
else if (s >= mid + 1) modify(s, e, Si, Ti, p3);
else modify(s, mid, Si, Ti, p2), modify(mid + 1, e, Si, Ti, p3);
upt(p);
}
inline clb ask(int s, int e, int p) {
clb res; int l = t[p].l, r = t[p].r;
if (l == s && r == e) {
double x, y;
if (t[p].cn) {
x = t[p].firX + t[p].addX; y = t[p].firY + t[p].addY;
res.sumX = x * (r - l + 1) +
1.0 * (l + r) * (r - l + 1)
/ 2.0;
res.sumY = y * (r - l + 1) +
1.0 * (l + r) * (r - l + 1)
/ 2.0;
res.sumXY = x * y * (r - l + 1) +
1.0 * (x + y) * (l + r) * (r - l + 1)
/ 2.0 + sumx2(l, r);
res.sumX2 = sqr(x) * (r - l + 1) +
x * (l + r) * (r - l + 1) + sumx2(l, r);
return res;
}
res.sumX = t[p].sumX + t[p].addX * (r - l + 1);
res.sumY = t[p].sumY + t[p].addY * (r - l + 1);
res.sumXY = t[p].sumXY + t[p].sumX * t[p].addY
+ t[p].sumY * t[p].addX + t[p].addX * t[p].addY * (r - l + 1);
res.sumX2 = t[p].sumX2 + 2.0 * t[p].addX * t[p].sumX
+ sqr(t[p].addX) * (r - l + 1);
return res;
}
int mid = l + r >> 1, p2 = t[p].lc, p3 = t[p].rc; downdate(p);
if (e <= mid) res = ask(s, e, p2);
else if (s >= mid + 1) res = ask(s, e, p3);
else res = ask(s, mid, p2) + ask(mid + 1, e, p3);
return upt(p), res;
}
inline double trans(int l, int r, clb res) {
double x = res.sumX, y = res.sumY, x2 = res.sumX2, xy = res.sumXY;
return (xy - x * y / (r - l + 1)) / (x2 - x * x / (r - l + 1));
}
int main() {
int i, op, x, y, u, v; n = read(); m = read();
for (i = 1; i <= n; i++) X[i] = read();
for (i = 1; i <= n; i++) Y[i] = read();
build(1, n, 1);
while (m--) {
op = read(); if (op == 2) {
x = read(); y = read(); u = read(); v = read();
change(x, y, u, v, 1);
}
else if (op == 3) {
x = read(); y = read(); u = read(); v = read();
modify(x, y, u, v, 1);
}
else {
x = read(); y = read();
printf("%.10lf\n", trans(x, y, ask(x, y, 1)));
}
}
return 0;
}