P1471 方差
阿新 • • 發佈:2021-10-30
運用一點初中知識可以知道
維護一下區間平方和和區間和就可以處理了
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m; int f; int x,y; double k; struct p{ double sum; double sqr; }po[400005]; double lazy[400005]; void pushdown(int ro,int l,int r){ if(lazy[ro]){ int mid=(l+r)>>1; double k=lazy[ro];lazy[ro]=0; lazy[ro<<1]+=k;lazy[ro<<1|1]+=k; po[ro<<1].sqr=po[ro<<1].sqr+2*k*po[ro<<1].sum+k*k*(mid-l+1); po[ro<<1].sum+=k*(mid-l+1); po[ro<<1|1].sqr=po[ro<<1|1].sqr+2*k*po[ro<<1|1].sum+k*k*(r-mid); po[ro<<1|1].sum+=k*(r-mid); } } void pushup(int r){ po[r].sqr=po[r<<1].sqr+po[r<<1|1].sqr; po[r].sum=po[r<<1].sum+po[r<<1|1].sum; } void add(int ro,int l,int r,int L,int R,double k){ if(L<=l&&r<=R){ po[ro].sqr=po[ro].sqr+2*k*po[ro].sum+k*k*(r-l+1); po[ro].sum+=k*(r-l+1); lazy[ro]+=k; return ; } pushdown(ro,l,r); int mid=(r+l)>>1; if(L<=mid) add(ro<<1,l,mid,L,R,k); if(R>mid) add(ro<<1|1,mid+1,r,L,R,k); pushup(ro); } double qsum(int ro,int l,int r,int L,int R){ if(L<=l&&r<=R){ return po[ro].sum; } pushdown(ro,l,r); int mid=(l+r)>>1; double ans=0; if(L<=mid) ans+=qsum(ro<<1,l,mid,L,R); if(R>mid) ans+=qsum(ro<<1|1,mid+1,r,L,R); return ans; } double qsqr(int ro,int l,int r,int L,int R){ if(L<=l&&r<=R){ return po[ro].sqr; } pushdown(ro,l,r); int mid=(l+r)>>1; double ans=0; if(L<=mid) ans+=qsqr(ro<<1,l,mid,L,R); if(R>mid) ans+=qsqr(ro<<1|1,mid+1,r,L,R); return ans; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%lf",&k); add(1,1,n,i,i,k); } for(int i=1;i<=m;++i){ scanf("%d",&f); if(f==1){ scanf("%d%d%lf",&x,&y,&k); add(1,1,n,x,y,k); } if(f==2){ scanf("%d%d",&x,&y); double su=qsum(1,1,n,x,y); //cout<<qsum(1,1,n,x,y)<<endl; //cout<<su<<endl; printf("%.4lf\n",(double)su/(y-x+1)); } if(f==3){ scanf("%d%d",&x,&y); double su=qsum(1,1,n,x,y); double sq=qsqr(1,1,n,x,y); printf("%.4lf\n",(double)sq/(y-x+1)-su*su/(double)(y-x+1)/(double)(y-x+1)); } } return 0; }