/* 将原式化简,会发现最后只需要维护四个东西,分别是:Σx,Σy,Σx*y,Σx*x。 区间加的时候x和y都很容易, Σx*y=Σ(x+S)*(y+T)=Σx*y+S*Σy+T*Σx+len*S*T Σx*x=Σ(x+S)*(x+S)=Σx*x+2*S*Σx+len*S*S 区间修改的时候 Σ(i+S)*(i+T)=Σi*i+(S+T)*Σi+len*S*T Σ(i+S)*(i+S)=Σi*i+2*S*Σi+len*S*S 注意区间加和区间修改的先后顺序,有区间修改时应该先修改在进行区间加; 而有区间加的时候,可以直接进行区间修改。 */ #include<cstdio> #include<cstring> #include<algorithm> #define N 400010 #define inf 1000000000 using namespace std; const double eps=1e-8; int n,m,X[N],Y[N]; double Xs[N],Ys[N],Sq[N],Mul[N],Xdlt[N],Ydlt[N]; double Is[N],Is2[N],Xcov[N],Ycov[N]; struct node{ double sx,sy,sq,ml; node(){sx=sy=sq=ml=0;} }; void update(int i){ Xs[i]=Xs[i<<1]+Xs[(i<<1)+1]; Ys[i]=Ys[i<<1]+Ys[(i<<1)+1]; Sq[i]=Sq[i<<1]+Sq[(i<<1)+1]; Mul[i]=Mul[i<<1]+Mul[(i<<1)+1]; } void Cov(int i,int l,int r,double cx,double cy){ double len=(r-l+1); Xdlt[i]=Ydlt[i]=0; Xcov[i]=cx;Ycov[i]=cy; Sq[i]=cx*cx*len+2*cx*Is[i]+Is2[i]; Mul[i]=cx*cy*len+(cx+cy)*Is[i]+Is2[i]; Xs[i]=cx*len+Is[i];Ys[i]=cy*len+Is[i]; } void Add(int i,int l,int r,double dx,double dy){ double len=r-l+1; if (Xcov[i]!=inf||Ycov[i]!=inf){ Cov(i,l,r,Xcov[i]+dx,Ycov[i]+dy); return; } Xdlt[i]+=dx;Ydlt[i]+=dy; Sq[i]+=dx*dx*len+2*dx*Xs[i]; Mul[i]+=dx*Ys[i]+dy*Xs[i]+dx*dy*len; Xs[i]+=dx*len;Ys[i]+=dy*len; } void pushdown(int i,int l,int r){ if (Xdlt[i]!=0||Ydlt[i]!=0){ int mid=(l+r)>>1; Add(i<<1,l,mid,Xdlt[i],Ydlt[i]); Add((i<<1)+1,mid+1,r,Xdlt[i],Ydlt[i]); Xdlt[i]=Ydlt[i]=0; } if (Xcov[i]!=inf||Ycov[i]!=inf){ int mid=(l+r)>>1; Cov(i<<1,l,mid,Xcov[i],Ycov[i]); Cov((i<<1)+1,mid+1,r,Xcov[i],Ycov[i]); Xcov[i]=Ycov[i]=inf; } } void build(int i,int l,int r){ Xcov[i]=Ycov[i]=inf; if (l==r){ double xx=X[l],yy=Y[l]; Xs[i]=xx;Ys[i]=yy; Sq[i]=xx*xx;Mul[i]=xx*yy; Is[i]=l;Is2[i]=(double)l*(double)l; return; } int mid=(l+r)>>1; build(i<<1,l,mid); build((i<<1)+1,mid+1,r); update(i); Is[i]=Is[i<<1]+Is[(i<<1)+1]; Is2[i]=Is2[i<<1]+Is2[(i<<1)+1]; } void ask(int i,int l,int r,int x,int y,node &ans){ if (x<=l&&y>=r){ ans.sx+=Xs[i];ans.sy+=Ys[i]; ans.sq+=Sq[i];ans.ml+=Mul[i]; return; } int mid=(l+r)>>1; pushdown(i,l,r); if (x<=mid) ask(i<<1,l,mid,x,y,ans); if (y>mid) ask((i<<1)+1,mid+1,r,x,y,ans); } double Getans(int l,int r){ node tmp; double avex,avey,len=r-l+1,up,down; up=down=0;ask(1,1,n,l,r,tmp); avex=tmp.sx/len;avey=tmp.sy/len; down=tmp.sq-2*avex*tmp.sx+avex*avex*len; up=tmp.ml-avey*tmp.sx-avex*tmp.sy+avex*avey*len; return up/down+eps; } void add(int i,int l,int r,int x,int y,double s,double t){ if (x<=l&&y>=r){Add(i,l,r,s,t);return;} int mid=(l+r)>>1; pushdown(i,l,r); if (x<=mid) add(i<<1,l,mid,x,y,s,t); if (y>mid) add((i<<1)+1,mid+1,r,x,y,s,t); update(i); } void cover(int i,int l,int r,int x,int y,double s,double t){ if (x<=l&&y>=r){Cov(i,l,r,s,t);return;} int mid=(l+r)>>1; pushdown(i,l,r); if (x<=mid) cover(i<<1,l,mid,x,y,s,t); if (y>mid) cover((i<<1)+1,mid+1,r,x,y,s,t); update(i); } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&X[i]); for (int i=1;i<=n;i++) scanf("%d",&Y[i]); build(1,1,n); for (int i=1;i<=m;i++){ int type,l,r,s,t; scanf("%d%d%d",&type,&l,&r); if (type==1) printf("%.10lf ",Getans(l,r)); if (type==2){ scanf("%d%d",&s,&t); add(1,1,n,l,r,s,t); } if (type==3){ scanf("%d%d",&s,&t); cover(1,1,n,l,r,s,t); } } return 0; }