4821: [Sdoi2017]相关分析
4821: [Sdoi2017]相关分析
分析:
大力拆式子,化简,然后线段树。注意精度问题与爆longlong问题。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> #define Root 1, n, 1 #define lc rt << 1 #define rc rt << 1 | 1 #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 using namespace std; typedef double DB; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int N = 100005; DB sx[N << 2], sy[N << 2], s[N << 2], s2[N << 2], tag[N << 2], taga[N << 2], tagb[N << 2], X[N], Y[N]; DB sum[N], sum2[N]; DB Sx, Sy, S, S2; int n; inline void pushup(int rt) { sx[rt] = sx[lc] + sx[rc]; sy[rt] = sy[lc] + sy[rc]; s2[rt] = s2[lc] + s2[rc]; s[rt] = s[lc] + s[rc]; } inline void col(int rt,int l,int r) { sy[rt] = sx[rt] = sum[r] - sum[l - 1]; s2[rt] = s[rt] = sum2[r] - sum2[l - 1]; tag[rt] = 1; taga[rt] = tagb[rt] = 0; } inline void add(int rt,DB len,DB a,DB b) { s[rt] += sx[rt] * b + sy[rt] * a + a * b * len; s2[rt] += a * a * len + 2 * a * sx[rt]; sx[rt] += a * len; sy[rt] += b * len; taga[rt] += a, tagb[rt] += b; } inline void pushdown(int rt,int l,int r) { int mid = (l + r) >> 1; if (tag[rt]) { col(lc, l, mid); col(rc, mid + 1, r); tag[rt] = 0; } if (taga[rt] || tagb[rt]) { // !!! add(lc, mid - l + 1, taga[rt], tagb[rt]); add(rc, r - mid, taga[rt], tagb[rt]); taga[rt] = tagb[rt] = 0; } } void build(int l,int r,int rt) { if (l == r) { sx[rt] = X[l], sy[rt] = Y[l], s[rt] = X[l] * Y[l], s2[rt] = X[l] * X[l]; return ; } int mid = (l + r) >> 1; build(lson), build(rson); pushup(rt); } void update(int l,int r,int rt,int L,int R,DB a,DB b) { if (L <= l && r <= R) { add(rt, r - l + 1, a, b); return ; } int mid = (l + r) >> 1; pushdown(rt, l, r); if (L <= mid) update(lson, L, R, a, b); if (R > mid) update(rson, L, R, a, b); pushup(rt); } void Change(int l,int r,int rt,int L,int R) { if (L <= l && r <= R) { col(rt, l, r); return ; } int mid = (l + r) >> 1; pushdown(rt, l, r); if (L <= mid) Change(lson, L, R); if (R > mid) Change(rson, L, R); pushup(rt); } void query(int l,int r,int rt,int L,int R) { if (L <= l && r <= R) { Sx += sx[rt], Sy += sy[rt], S += s[rt], S2 += s2[rt]; return ; } int mid = (l + r) >> 1; pushdown(rt, l, r); if (L <= mid) query(lson, L, R); if (R > mid) query(rson, L, R); } void Ask() { int l = read(), r = read(); Sx = Sy = S = S2 = 0; query(Root, l, r); double x = 1.0 * Sx / (r - l + 1), y = 1.0 * Sy / (r - l + 1); // double u = S - Sy * x - Sx * y + x * y * (r - l + 1); // double d = S2 + x * x * (r - l + 1) - 2 * Sx * x; double u = S - y * Sx, d = S2 - x * Sx; printf("%.10lf\n", (double)(u / d)); } void work1() { int l = read(), r = read(); DB a = (DB)read(), b = (DB)read(); update(Root, l, r, a, b); } void work2() { int l = read(), r = read(); DB a = (DB)read(), b = (DB)read(); Change(Root, l, r); update(Root, l, r, a, b); } int main() { n = read();int m = read(); for (int i = 1; i <= n; ++i) { sum[i] = sum[i - 1] + 1.0 * i; sum2[i] = sum2[i - 1] + 1.0 * i * i; // 此处报int !!! } for (int i = 1; i <= n; ++i) X[i] = (DB)read(); for (int i = 1; i <= n; ++i) Y[i] = (DB)read(); build(Root); while (m --) { int opt = read(); if (opt == 1) Ask(); else if (opt == 2) work1(); else work2(); } return 0; }