洛谷 P3707 [SDOI2017]相关分析 线段树

题目描述

Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度、颜色等等,进而估算出星星的距离,半径等等。

Frank不仅喜欢观测,还喜欢分析观测到的数据。他经常分析两个参数之间(比如亮度和半径)是否存在某种关系。

现在Frank要分析参数 X 与 Y 之间的关系。他有 n 组观测数据,第 i 组观测数据记录了 x i y i
他需要一下几种操作
1 L , R
用直线拟合第 L 组到第 R 组观测数据。
x ¯ 表示这些观测数据中 x 的平均数,
y ¯ 表示这些观测数据中 y 的平均数,即
x ¯ = 1 R L + 1 i = L R x i
y ¯ = 1 R L + 1 i = L R y i

如果直线方程是 y=ax+b,那么 a,b 应当这样计算:

a = i = L R ( x i x ¯ ) ( y i y ¯ ) i = L R ( x i x ¯ ) 2

你需要帮助Frank计算 a 。

2 L,R,S,T :
Frank发现测量数据第 L 组到第 R 组数据有误差,对每个 i 满足 L i R x i 需要加上 S , y i 需要加上 T。

3 L,R,S,T :
Frank发现第 LL 组到第 RR 组数据需要修改,对于每个 i 满足 L i R , x i ​ 需要修改为 (S+i)(S+i) , y i 需要修改为 (T+i)(T+i) 。

输入输出格式

输入格式:
第一行两个数 n,m ,表示观测数据组数和操作次数。

接下来一行 n 个数,第 i 个数是 x i

接下来一行 n 个数,第 i 个数是 y i y

接下来 m 行,表示操作,格式见题目描述。

输出格式:
对于每个1操作,输出一行,表示直线斜率 a 。选手输出与标准输出的绝对误差或相对误差不超过 10 5
即为正确。

输入输出样例

输入样例#1:
3 5
1 2 3
1 2 3
1 1 3
2 2 3 -3 2
1 1 2
3 1 2 2 1
1 1 3
输出样例#1:
1.0000000000
-1.5000000000
-0.6153846154
说明

对于20%的数据 1 n , m 1000

另有20%的数据,没有3操作,且2操作中 S=0

另有30%的数据,没有3操作。

对于100%的数据, 1 n , m 10 5 , 0 | S | , | T | 10 5 , 0 | x i | , | y i | 10 5

保证1操作不会出现分母为 0 的情况。

时间限制:1s

空间限制:128MB

分析:要求的式子(回归方程)可以化成一下形式,

a = i = L R x i y i ( R L + 1 ) x ¯ y ¯ i = L R x i 2 ( R L + 1 ) x ¯ 2

然后可以线段树维护 x i y i x i y i x i 2 ,然后区间加可以打lazy,操作3要先把lazy清掉,再加上i,然后相当于跑一个操作2。

#include <bits/stdc++.h>
#define inline inline __attribute__((always_inline))
using namespace std;

const int N=1e5+5,inf=1061109567;
struct nodetype {
    double sx2,sxy,sx,sy;
    int t2s,t3s,t2t,t3t;
}t[N<<3];
int x[N],y[N],n;
typedef long long LL;

#define lson (Node<<1)
#define rson ((Node<<1)|1)
void Build(int Node,int l,int r) {
    if(l==r) {
        t[Node]={x[l]*1.0*x[l],x[l]*1.0*y[l],x[l],y[l],inf,inf,inf,inf};
        return;
    }
    int mid=(l+r)>>1;
    Build(lson,l,mid); Build(rson,mid+1,r);
    t[Node]={t[lson].sx2+t[rson].sx2,t[lson].sxy+t[rson].sxy,t[lson].sx+t[rson].sx,t[lson].sy+t[rson].sy,inf,inf,inf,inf};
}

#define sqr(x) ((x)*1.0*(x))
inline void deal3(int Node,int l,int r,int S,int T) {
    LL len=r-l+1,sum=((1+len)*len)>>1,sqsum=(len*(len+1)*(2ll*len+1))/6;
    t[Node].sx2=len*sqr(S)+2.0*S*sum+sqsum;
    t[Node].sxy=len*S*T+sum*S+sum*T+sqsum;
    t[Node].sx=len*S+sum,t[Node].sy=len*T+sum;
    t[Node].t2s=t[Node].t2t=inf,t[Node].t3s=S,t[Node].t3t=T;
}

inline void deal2(int Node,int l,int r,int S,int T) {
    LL len=r-l+1;
    t[Node].sx2+=2ll*t[Node].sx*S+len*sqr(S);
    t[Node].sxy+=t[Node].sx*T+t[Node].sy*S+len*S*T;
    t[Node].sx+=len*S,t[Node].sy+=len*T;
    if(t[Node].t2s!=inf) t[Node].t2s+=S,t[Node].t2t+=T; else t[Node].t2s=S,t[Node].t2t=T;
}

inline void updlzy(int Node,int l,int r) {
    if(t[Node].t2s==inf&&t[Node].t3s==inf) return;
    int mid=(l+r)>>1;
    if(t[Node].t3s!=inf) {
        deal3(lson,l,mid,t[Node].t3s,t[Node].t3t); deal3(rson,mid+1,r,t[Node].t3s+mid-l+1,t[Node].t3t+mid-l+1);
        t[Node].t3s=t[Node].t3t=inf;
    }
    if(t[Node].t2s!=inf) {
        deal2(lson,l,mid,t[Node].t2s,t[Node].t2t); deal2(rson,mid+1,r,t[Node].t2s,t[Node].t2t);
        t[Node].t2s=t[Node].t2t=inf;
    }
}

void Modify2(int Node,int l,int r,int L,int R,int S,int T) {
    LL len=r-l+1;
    updlzy(Node,l,r);
    if(L<=l&&r<=R) {
        t[Node].sx2+=2.0*S*t[Node].sx+len*sqr(S);
        t[Node].sxy+=t[Node].sx*T+t[Node].sy*S+len*S*T;
        t[Node].sx+=S*len; t[Node].sy+=T*len;
        if(t[Node].t2s!=inf) t[Node].t2s+=S,t[Node].t2t+=T; else t[Node].t2s=S,t[Node].t2t=T;
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid) Modify2(lson,l,mid,L,R,S,T);
    if(mid+1<=R) Modify2(rson,mid+1,r,L,R,S,T);
    t[Node]={t[lson].sx2+t[rson].sx2,t[lson].sxy+t[rson].sxy,t[lson].sx+t[rson].sx,t[lson].sy+t[rson].sy,inf,inf,inf,inf};
}

void Modify3(int Node,int l,int r,int L,int R,int S,int T) {
    LL len=r-l+1;
    updlzy(Node,l,r);
    if(L<=l&&r<=R) {
        LL sum=((1+len)*len)>>1,sqsum=(len*(len+1)*(2ll*len+1))/6;
        t[Node].sx2=len*sqr(S)+2.0*S*sum+sqsum;
        t[Node].sxy=len*S*T+sum*S+sum*T+sqsum;
        t[Node].sx=len*S+sum,t[Node].sy=len*T+sum;
        t[Node].t2s=t[Node].t2t=inf,t[Node].t3s=S,t[Node].t3t=T;
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid) Modify3(lson,l,mid,L,R,S,T);
    if(mid+1<=R) Modify3(rson,mid+1,r,L,R,S+mid-l+1,T+mid-l+1);
    t[Node]={t[lson].sx2+t[rson].sx2,t[lson].sxy+t[rson].sxy,t[lson].sx+t[rson].sx,t[lson].sy+t[rson].sy,inf,inf,inf,inf};
}

struct restp {
    double sx2,sxy,sx,sy;
    inline restp(double x2=0,double xy=0,double x=0,double y=0) {sx2=x2,sxy=xy,sx=x,sy=y;}
    inline void operator+= (restp b) {sx2+=b.sx2,sxy+=b.sxy,sx+=b.sx,sy+=b.sy;}
};

restp Query(int Node,int l,int r,int L,int R) {
    updlzy(Node,l,r);
    if(L<=l&&r<=R) return restp(t[Node].sx2,t[Node].sxy,t[Node].sx,t[Node].sy);
    restp ans; int mid=(l+r)>>1;
    if(L<=mid) ans=Query(lson,l,mid,L,R);
    if(mid+1<=R) ans+=Query(rson,mid+1,r,L,R);
    return ans;
}

inline int readin() {
    char c=getchar(); bool neg=(c=='-');
    while(!('0'<=c&&c<='9')) c=getchar(),neg|=(c=='-');
    int ret=0;
    for(;'0'<=c&&c<='9';c=getchar()) ret=ret*10+c-48;
    return neg ? -ret : ret;
}

int main() {
    //freopen("1.in","r",stdin);
    //freopen("1.ans","w",stdout);

    n=readin(); int m=readin();
    for(int i=1;i<=n;++i) x[i]=readin();
    for(int i=1;i<=n;++i) y[i]=readin();
    int tp,L,R,S,T;
    restp r;
    Build(1,1,n);
    while(m--) {
        tp=readin(),L=readin(),R=readin();
        if(tp==1) {
            r=Query(1,1,n,L,R);
            int len=R-L+1;
            printf("%.10lf\n",(r.sxy-double(r.sx*r.sy)/len)/(r.sx2-double(r.sx*r.sx)/len));
        }
        else {
            S=readin(),T=readin();
            if(tp==2) Modify2(1,1,n,L,R,S,T);
            else Modify3(1,1,n,L,R,S,T);
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/liangzihao1/article/details/80782544