线段树
这题真是无聊
把式子拆开,然后可知维护xi,yi,xi^2,xi*yi,重点在于标记下传,当我们进行2号操作时,直接累加进答案和标记即可,进行3号操作时,update时先把自己这层赋值成要改变的值,再清空这层2号标记,每次pushdown把这层的下一层的标记清空,因为下一层被覆盖了,pushdown先执行3号标记,再执行2号标记,因为存在的2号标记肯定在3号标记后打的,否则肯定会被清空,所以2号标记应该在三号标记后。
而下一层的2号标记肯定是在三号标记之前打的,因为标记已经下传。
#include<bits/stdc++.h> using namespace std; typedef double ld; const int N = 100010; int n, m; ld x[N], y[N]; struct node { double sumx, sumy, sumxx, sumxy; node(ld sumx = 0, ld sumy = 0, ld sumxx = 0, ld sumxy = 0) : sumx(sumx), sumy(sumy), sumxx(sumxx), sumxy(sumxy) {} void print() { printf("sumx=%.10f sumy=%.10f sumxx=%.10f sumxy=%.10f ", sumx, sumy, sumxx, sumxy); } }; struct seg { node tree[N << 2]; ld tagx2[N << 2], tagy2[N << 2], tagx3[N << 2], tagy3[N << 2]; bool can1[N << 2], can2[N << 2]; ld calc(ld x) { return (ld)x * (ld)(x + 1) * (ld)(2 * x + 1) / 6; } void pushdown(int o, int l, int r) { int mid = (l + r) >> 1; if(can1[o]) { tree[o << 1].sumx = (ld)(mid - l + 1) * tagx3[o] + (ld)(mid + l) * (ld)(mid - l + 1) / 2.0; tree[o << 1 | 1].sumx = (ld)(r - mid) * tagx3[o] + (ld)(r + mid + 1) * (ld)(r - mid) / 2.0; tree[o << 1].sumy = (ld)(mid - l + 1) * tagy3[o] + (ld)(mid + l) * (ld)(mid - l + 1) / 2.0; tree[o << 1 | 1].sumy = (ld)(r - mid) * tagy3[o] + (ld)(r + mid + 1) * (ld)(r - mid) / 2.0; tree[o << 1].sumxx = calc(tagx3[o] + mid) - calc(tagx3[o] + l - 1); tree[o << 1 | 1].sumxx = calc(tagx3[o] + r) - calc(tagx3[o] + mid); tree[o << 1].sumxy = (ld)(mid - l + 1) * tagx3[o] * tagy3[o] + (ld)(tagx3[o] + tagy3[o]) * (ld)(mid + l) * (ld)(mid - l + 1) / 2.0 + calc(mid) - calc(l - 1); tree[o << 1 | 1].sumxy = (ld)(r - mid) * tagx3[o] * tagy3[o] + (ld)(tagx3[o] + tagy3[o]) * (ld)(r + mid + 1) * (ld)(r - mid) / 2.0 + calc(r) - calc(mid); tagx3[o << 1] = tagx3[o << 1 | 1] = tagx3[o]; tagy3[o << 1] = tagy3[o << 1 | 1] = tagy3[o]; tagx3[o] = tagy3[o] = 0; tagx2[o << 1] = tagx2[o << 1 | 1] = tagy2[o << 1] = tagy2[o << 1 | 1] = 0; can2[o << 1] = can2[o << 1 | 1] = 0; can1[o << 1] = can1[o << 1 | 1] = can1[o]; can1[o] = 0; } if(can2[o]) { tree[o << 1].sumxx += 2.0 * tree[o << 1].sumx * tagx2[o] + (ld)(mid - l + 1) * tagx2[o] * tagx2[o]; tree[o << 1 | 1].sumxx += 2.0 * tree[o << 1 | 1].sumx * tagx2[o] + (ld)(r - mid) * tagx2[o] * tagx2[o]; tree[o << 1].sumxy += tree[o << 1].sumx * tagy2[o] + tree[o << 1].sumy * tagx2[o] + (ld)(mid - l + 1) * tagx2[o] * tagy2[o]; tree[o << 1 | 1].sumxy += tree[o << 1 | 1].sumx * tagy2[o] + tree[o << 1 | 1].sumy * tagx2[o] + (ld)(r - mid) * tagx2[o] * tagy2[o]; tree[o << 1].sumx += tagx2[o] * (ld)(mid - l + 1); tree[o << 1 | 1].sumx += tagx2[o] * (ld)(r - mid); tree[o << 1].sumy += tagy2[o] * (ld)(mid - l + 1); tree[o << 1 | 1].sumy += tagy2[o] * (ld)(r - mid); tagx2[o << 1] += tagx2[o]; tagx2[o << 1 | 1] += tagx2[o]; tagy2[o << 1] += tagy2[o]; tagy2[o << 1 | 1] += tagy2[o]; tagx2[o] = 0; tagy2[o] = 0; can2[o << 1] = can2[o << 1 | 1] = can2[o]; can2[o] = 0; } } node merge(node B, node C) { node A; A.sumx = B.sumx + C.sumx; A.sumy = B.sumy + C.sumy; A.sumxx = B.sumxx + C.sumxx; A.sumxy = B.sumxy + C.sumxy; return A; } void build(int l, int r, int o) { if(l == r) { tree[o] = node(x[l], y[l], x[l] * x[l], x[l] * y[l]); return; } int mid = (l + r) >> 1; build(l, mid, o << 1); build(mid + 1, r, o << 1 | 1); tree[o] = merge(tree[o << 1], tree[o << 1 | 1]); } node query(int l, int r, int o, int a, int b) { if(l > b || r < a) return tree[0]; if(l >= a && r <= b) return tree[o]; int mid = (l + r) >> 1; pushdown(o, l, r); node tx = query(l, mid, o << 1, a, b), ty = query(mid + 1, r, o << 1 | 1, a, b); return merge(tx, ty); } void update2(int l, int r, int o, int a, int b, ld s, ld t) { if(l > b || r < a) return; if(l >= a && r <= b) { tagx2[o] += s; tagy2[o] += t; tree[o].sumxx += 2.0 * tree[o].sumx * s + (ld)(r - l + 1) * s * s; tree[o].sumxy += t * tree[o].sumx + s * tree[o].sumy + (ld)(r - l + 1) * s * t; tree[o].sumx += (ld)(r - l + 1) * s; tree[o].sumy += (ld)(r - l + 1) * t; can2[o] = 1; return; } pushdown(o, l, r); int mid = (l + r) >> 1; update2(l, mid, o << 1, a, b, s, t); update2(mid + 1, r, o << 1 | 1, a, b, s, t); tree[o] = merge(tree[o << 1], tree[o << 1 | 1]); } void update3(int l, int r, int o, int a, int b, ld s, ld t) { if(l > b || r < a) return; if(l >= a && r <= b) { tagx3[o] = s; tagy3[o] = t; tagx2[o] = tagy2[o] = 0; tree[o].sumx = (ld)(r - l + 1) * s + (ld)(l + r) * (ld)(r - l + 1) / 2.0; tree[o].sumy = (ld)(r - l + 1) * t + (ld)(l + r) * (ld)(r - l + 1) / 2.0; tree[o].sumxx = calc(s + r) - calc(s + l - 1); tree[o].sumxy = (ld)(r - l + 1) * s * t + ((ld)(l + r) * (ld)(r - l + 1) / 2.0) * (ld)(s + t) + calc(r) - calc(l - 1); can1[o] = 1; can2[o] = 0; return; } pushdown(o, l, r); int mid = (l + r) >> 1; update3(l, mid, o << 1, a, b, s, t); update3(mid + 1, r, o << 1 | 1, a, b, s, t); tree[o] = merge(tree[o << 1], tree[o << 1 | 1]); } } t; int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%lf", &x[i]); for(int i = 1; i <= n; ++i) scanf("%lf", &y[i]); t.build(1, n, 1); for(int i = 1; i <= m; ++i) { int opt, l, r; ld S, T; scanf("%d", &opt); if(opt == 1) { scanf("%d%d", &l, &r); node o = t.query(1, n, 1, l, r); ld ox = o.sumx / (ld)(r - l + 1), oy = o.sumy / (ld)(r - l + 1); ld up = ((ld)(r - l + 1) * o.sumxy - o.sumx * o.sumy), down = ((ld)(r - l + 1) * o.sumxx - o.sumx * o.sumx), ans = up / down; printf("%.10f ", ans); } if(opt == 2) { scanf("%d%d%lf%lf", &l, &r, &S, &T); t.update2(1, n, 1, l, r, S, T); } if(opt == 3) { scanf("%d%d%lf%lf", &l, &r, &S, &T); t.update3(1, n, 1, l, r, S, T); } } return 0; }