题目描述
Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度、颜色等等,进而估算出星星的距离,半径等等。
Frank不仅喜欢观测,还喜欢分析观测到的数据。他经常分析两个参数之间(比如亮度和半径)是否存在某种关系。
现在Frank要分析参数 X 与 Y 之间的关系。他有 n 组观测数据,第 i 组观测数据记录了
和
。
他需要一下几种操作
1
:
用直线拟合第 L 组到第 R 组观测数据。
用
表示这些观测数据中 x 的平均数,
用
表示这些观测数据中 y 的平均数,即
如果直线方程是 y=ax+b,那么 a,b 应当这样计算:
你需要帮助Frank计算 a 。
2 L,R,S,T :
Frank发现测量数据第 L 组到第 R 组数据有误差,对每个 i 满足
,
需要加上 S ,
需要加上 T。
3 L,R,S,T :
Frank发现第 LL 组到第 RR 组数据需要修改,对于每个 i 满足
,
需要修改为 (S+i)(S+i) ,
需要修改为 (T+i)(T+i) 。
输入输出格式
输入格式:
第一行两个数 n,m ,表示观测数据组数和操作次数。
接下来一行 n 个数,第 i 个数是 。
接下来一行 n 个数,第 i 个数是 。
接下来 m 行,表示操作,格式见题目描述。
输出格式:
对于每个1操作,输出一行,表示直线斜率 a 。选手输出与标准输出的绝对误差或相对误差不超过
即为正确。
输入输出样例
输入样例#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%的数据
另有20%的数据,没有3操作,且2操作中 S=0
另有30%的数据,没有3操作。
对于100%的数据,
保证1操作不会出现分母为 0 的情况。
时间限制:1s
空间限制:128MB
分析:要求的式子(回归方程)可以化成一下形式,
然后可以线段树维护 , , , ,然后区间加可以打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;
}