• Loj 2005 相关分析


    Loj 2005 相关分析

    • 大力把式子拆开.

    [egin{aligned} a &= frac {sum_{i=L}^{R} (x_i-ar{x})(y_i-ar{y})} {sum_{i=L}^{R} (x_i-ar{x})^2}\ &= frac {sum_{i=L}^R (x_iy_i+ar{x}ar{y}-ar{x}y_i-ar{y}x_i)} {sum_{i=L}^{R} (x_i^2-2ar{x}x_i+ar{x}^2)}\ &=frac {sum_{i=L}^R x_iy_i+(R-L+1)cdotar{x}ar{y}-ar{x}sum_{i=L}^{R}y_i-ar{y}sum_{i=L}^{R}x_i} {sum_{i=L}^{R} x_i^2-2ar{x}sum_{i=L}^{R}x_i+(R-L+1)*ar{x}^2} end{aligned} ]

    • 于是只需要用线段树维护区间的 (sum x_i,sum y_i,sum x_i y_i,sum x_i^2) .
    • 考虑两种修改操作,第一种显然很简单,第二种可以看成对区间执行 (x_i=i,y_i=i) ,再进行第一种操作.修改之后这四个值都可以利用公式 (O(1)) 算出.于是维护三个标记就可以了.
    • 注意中间运算时开 (long long,double) ,防止爆掉.

    其实代码写得有些冗长.可以把结果和标记写在两个数组中,这样修改查询的时候传入下标应该会短不少.

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		fh=-1,jp=getchar();
    	while (jp>='0'&&jp<='9')
    		out=out*10+jp-'0',jp=getchar();
    	return out*fh;
    }
    const int MAXN=1e5+10;
    double x[MAXN],y[MAXN];
    double sqr(double x)
    {
    	double res=1.0*x*(x+1)*(2*x+1);
    	res/=6;
    	return res;
    }
    struct node
    {
    	int l,r,siz;
    	double sumx,sumy,sumsq,sumpro;
    	bool tag_cover;
    	double tag_addx,tag_addy;
    	node()
    	{
    		tag_addx=0;
    		tag_addy=0;
    		tag_cover=false;
    	}
    } Tree[MAXN<<2];
    #define root Tree[o]
    #define lson Tree[o<<1]
    #define rson Tree[o<<1|1]
    void pushup(int o)
    {
    	root.sumx=lson.sumx+rson.sumx;
    	root.sumy=lson.sumy+rson.sumy;
    	root.sumsq=lson.sumsq+rson.sumsq;
    	root.sumpro=lson.sumpro+rson.sumpro;
    }
    void modifiy_addx(int o,double c)
    {
    	root.sumsq+=root.siz*c*c+2*c*root.sumx;
    	root.sumpro+=c*root.sumy;
    	root.sumx+=root.siz*c;
    	root.tag_addx+=c;
    }
    void modifiy_addy(int o,double c)
    {
    	root.sumpro+=c*root.sumx;
    	root.sumy+=root.siz*c;
    	root.tag_addy+=c;
    }
    void modifiy_cover(int o)
    {
    	root.sumx=root.sumy=1LL*(root.l+root.r)*root.siz/2.0;
    	root.sumpro=root.sumsq=sqr(root.r)-sqr(root.l-1);
    	root.tag_addx=root.tag_addy=0;
    	root.tag_cover=true;
    }
    void pushdown(int o)
    {
    	if(root.tag_cover)
    		{
    			modifiy_cover(o<<1);
    			modifiy_cover(o<<1|1);
    			root.tag_cover=false;
    		}
    	if(root.tag_addx)
    		{
    			modifiy_addx(o<<1,root.tag_addx);
    			modifiy_addx(o<<1|1,root.tag_addx);
    			root.tag_addx=0;
    		}
    	if(root.tag_addy)
    		{
    			modifiy_addy(o<<1,root.tag_addy);
    			modifiy_addy(o<<1|1,root.tag_addy);
    			root.tag_addy=0;
    		}
    }
    void BuildTree(int o,int l,int r)
    {
    	root.l=l,root.r=r,root.siz=r-l+1;
    	if(l==r)
    		{
    			root.sumx=x[l];
    			root.sumy=y[l];
    			root.sumpro=x[l]*y[l];
    			root.sumsq=x[l]*x[l];
    			return;
    		}
    	int mid=(l+r)>>1;
    	BuildTree(o<<1,l,mid);
    	BuildTree(o<<1|1,mid+1,r);
    	pushup(o);
    }
    void update_addx(int o,int L,int R,double c)
    {
    	int l=root.l,r=root.r;
    	if(l>R || L>r)
    		return;
    	if(L<=l && r<=R)
    		{
    			modifiy_addx(o,c);
    			return;
    		}
    	pushdown(o);
    	int mid=(l+r)>>1;
    	if(L<=mid)
    		update_addx(o<<1,L,R,c);
    	if(R>mid)
    		update_addx(o<<1|1,L,R,c);
    	pushup(o);
    }
    void update_addy(int o,int L,int R,double c)
    {
    	int l=root.l,r=root.r;
    	if(l>R || L>r)
    		return;
    	if(L<=l && r<=R)
    		{
    			modifiy_addy(o,c);
    			return;
    		}
    	pushdown(o);
    	int mid=(l+r)>>1;
    	if(L<=mid)
    		update_addy(o<<1,L,R,c);
    	if(R>mid)
    		update_addy(o<<1|1,L,R,c);
    	pushup(o);
    }
    void update_cover(int o,int L,int R)
    {
    	int l=root.l,r=root.r;
    	if(l>R || L>r)
    		return;
    	if(L<=l && r<=R)
    		{
    			modifiy_cover(o);
    			return;
    		}
    	pushdown(o);
    	int mid=(l+r)>>1;
    	if(L<=mid)
    		update_cover(o<<1,L,R);
    	if(R>mid)
    		update_cover(o<<1|1,L,R);
    	pushup(o);
    }
    double query_sumx(int o,int L,int R)
    {
    	int l=root.l,r=root.r;
    	if(l>R || L>r)
    		return 0;
    	if(L<=l && r<=R)
    		return root.sumx;
    	double res=0;
    	pushdown(o);
    	int mid=(l+r)>>1;
    	if(L<=mid)
    		res+=query_sumx(o<<1,L,R);
    	if(R>mid)
    		res+=query_sumx(o<<1|1,L,R);
    	return res;
    }
    double query_sumy(int o,int L,int R)
    {
    	int l=root.l,r=root.r;
    	if(l>R || L>r)
    		return 0;
    	if(L<=l && r<=R)
    		return root.sumy;
    	double res=0;
    	pushdown(o);
    	int mid=(l+r)>>1;
    	if(L<=mid)
    		res+=query_sumy(o<<1,L,R);
    	if(R>mid)
    		res+=query_sumy(o<<1|1,L,R);
    	return res;
    }
    double query_sumpro(int o,int L,int R)
    {
    	int l=root.l,r=root.r;
    	if(l>R || L>r)
    		return 0;
    	if(L<=l && r<=R)
    		return root.sumpro;
    	double res=0;
    	pushdown(o);
    	int mid=(l+r)>>1;
    	if(L<=mid)
    		res+=query_sumpro(o<<1,L,R);
    	if(R>mid)
    		res+=query_sumpro(o<<1|1,L,R);
    	return res;
    }
    double query_sumsqr(int o,int L,int R)
    {
    	int l=root.l,r=root.r;
    	if(l>R || L>r)
    		return 0;
    	if(L<=l && r<=R)
    		return root.sumsq;
    	double res=0;
    	pushdown(o);
    	int mid=(l+r)>>1;
    	if(L<=mid)
    		res+=query_sumsqr(o<<1,L,R);
    	if(R>mid)
    		res+=query_sumsqr(o<<1|1,L,R);
    	return res;
    }
    int n,m;
    int main()
    {
    	n=read(),m=read();
    	for(int i=1; i<=n; ++i)
    		scanf("%lf",&x[i]);
    	for(int i=1; i<=n; ++i)
    		scanf("%lf",&y[i]);
    	BuildTree(1,1,n);
    	double S,T;
    	while(m--)
    		{
    			int op=read();
    			if(op==1)
    				{
    					int L=read(),R=read();
    					double totx=query_sumx(1,L,R);
    					double toty=query_sumy(1,L,R);
    					double avrx=totx/(R-L+1);
    					double avry=toty/(R-L+1);
    					double ans=query_sumpro(1,L,R)+(R-L+1)*avrx*avry-toty*avrx-totx*avry;
    					ans/=query_sumsqr(1,L,R)+(R-L+1)*avrx*avrx-2*avrx*totx;
    					printf("%.10lf
    ",ans);
    				}
    			else if(op==2)
    				{
    					int L=read(),R=read();
    					scanf("%lf%lf",&S,&T);
    					update_addx(1,L,R,S);
    					update_addy(1,L,R,T);
    				}
    			else
    				{
    					int L=read(),R=read();
    					scanf("%lf%lf",&S,&T);
    					update_cover(1,L,R);
    					update_addx(1,L,R,S);
    					update_addy(1,L,R,T);
    				}
    		}
    	return 0;
    }
    
  • 相关阅读:
    Android详细的对话框AlertDialog.Builder使用方法 枫
    提高ASP.NET网站性能的方法 枫
    百度地图使用标注 枫
    C# 调用 .bat 文件的实现代码 枫
    mssqll2008下只显示相关的登陆操作 枫
    利用MSSQL排序规则,查询区分大小写的数据 枫
    Sql server 删除重复记录的SQL语句 枫
    open与fopen 文件描述符与文件指针
    android获得屏幕高度和宽度
    C语言:void swap(int &a, int &b);出错
  • 原文地址:https://www.cnblogs.com/jklover/p/10614239.html
Copyright © 2020-2023  润新知