相关分析

/*
    将原式化简,会发现最后只需要维护四个东西,分别是:Σ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;
}
原文地址:https://www.cnblogs.com/harden/p/6706149.html