zoukankan      html  css  js  c++  java
  • Luogu P1471 方差

    题目传送门

    开了十倍空间才过是什么鬼?该不会我线段树炸了吧……
    细思恐极


    平均数都会求,维护区间和,到时候除一下就好了。

    方差的求法如下
    (用的Luogu的图片)
    因为要维护一个平方,我们可以考虑使用van♂完全平方公式将它拆开,这样只用线段树维护区间和和区间平方和就可以了。
    对于区间修改,同样使用完全平方公式。

    要注意的一点是,修改时,要先修改平方和,再修改和,因为我们修改平方和时要用到区间和。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define ls p<<1
    #define rs p<<1|1
    #define mid ((l+r)>>1)
    using namespace std;
    struct zzz{
    	double sum,pf;
    }tree[1000010<<2];
    double tag[1000010<<2],a[1000010];
    inline void up(int p){
    	tree[p].sum=tree[ls].sum+tree[rs].sum;
    	tree[p].pf=tree[ls].pf+tree[rs].pf;
    }
    void build(int l,int r,int p){
    	if(l==r){
    		tree[p].sum=a[l];
    		tree[p].pf=a[l]*a[l];
    		return ;
    	}
    	build(l,mid,ls); build(mid+1,r,rs);
    	up(p);
    }
    inline void down(int l,int r,int p){
    //用完全平方公式修改平方和
    	tree[ls].pf+=2*tree[ls].sum*tag[p]+tag[p]*tag[p]*(mid-l+1);
    	tree[rs].pf+=2*tree[rs].sum*tag[p]+tag[p]*tag[p]*(r-mid);
    //维护区间和
    	tree[ls].sum+=tag[p]*(mid-l+1);
    	tree[rs].sum+=tag[p]*(r-mid);
    	tag[ls]+=tag[p]; tag[rs]+=tag[p]; tag[p]=0;
    }
    void update(int l,int r,int p,int nl,int nr,double k){
    	if(l>=nl&&r<=nr){
    		tree[p].pf+=2*tree[p].sum*k+k*k*(r-l+1);
    		tree[p].sum+=k*(r-l+1);
    		tag[p]+=k;
    		return ;
    	}
    	down(l,r,p);
    	if(nl<=mid) update(l,mid,ls,nl,nr,k);
    	if(nr>mid) update(mid+1,r,rs,nl,nr,k);
    	up(p);
    }
    double query(int l,int r,int p,int nl,int nr){
    	double ans=0;
    	down(l,r,p);
    	if(l>=nl&&r<=nr) return tree[p].sum;
    	if(nl<=mid) ans+=query(l,mid,ls,nl,nr);
    	if(nr>mid) ans+=query(mid+1,r,rs,nl,nr);
    	return ans;
    }
    double query2(int l,int r,int p,int nl,int nr){
    	double ans=0;
    	down(l,r,p);
    	if(l>=nl&&r<=nr) return tree[p].pf;
    	if(nl<=mid) ans+=query2(l,mid,ls,nl,nr);
    	if(nr>mid) ans+=query2(mid+1,r,rs,nl,nr);
    	return ans;
    }
    int read(){
    	int k=0,f=1; char c=getchar();
    	for(;c<'0'||c>'9';c=getchar())
    	  if(c=='-') f=-1;
    	for(;c>='0'&&c<='9';c=getchar())
    	  k=k*10+c-48;
    	return k*f;
    }
    int main(){
    	int n=read(),m=read();
    	for(int i=1;i<=n;i++) scanf("%lf",&a[i]);
    	build(1,n,1);
    	for(int i=1;i<=m;i++){
    		int opt=read(),l=read(),r=read();
    		if(opt==1){
    			double k; scanf("%lf",&k);
    			update(1,n,1,l,r,k);
    		}
    		if(opt==2){
    			printf("%.4lf
    ",query(1,n,1,l,r)/(r-l+1));
    		}
    		if(opt==3){
    			double sum=query(1,n,1,l,r);
    			double pj=sum/(r-l+1);
    			double pf=query2(1,n,1,l,r);
    			printf("%.4lf
    ",(pf-2*sum*pj+pj*pj*(r-l+1))/(r-l+1));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    GetDlgItem
    vc中调用其他应用程序的方法(函数) winexec,shellexecute ,createprocess
    C #中的几个线程同步对象方法 zz
    vc中调用exe的方法
    函数PlaySound和sndPlaySound的用法
    Radio Button的使用
    用Event实现线程同步
    C++学习随笔之九:类和动态内存分配
    C++学习随笔之七:对象和类
    C++学习随笔之二:数据处理
  • 原文地址:https://www.cnblogs.com/morslin/p/11854924.html
Copyright © 2011-2022 走看看