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;
}

 

posted @ 2019-02-15 20:38  MJT12044  阅读(167)  评论(0编辑  收藏  举报