zoukankan      html  css  js  c++  java
  • 「SDOI2017」相关分析(用线段树维护平方和)

    题目

    题目

    做法

    啊,这道题目一点思路都没有啊。

    这么神奇的吗。

    就是死命的推式子,这里用一下这位大佬的证明。
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    当然,写这个博客主要是想讲一下维护平方和和区间加减。

    首先,区间的(lazy)标记具有可加性:((x+k+k)^2=(x+2k)^2),因此,(lazy)标记可以叠加,只要计算每一个(lazy)标记会对维护的值产生多少的贡献即可。

    非常的优秀呢。

    因为用了别人太多证明了,所以用转载

    #include<cstdio>
    #include<cstring>
    #define  N  110000
    #define  NN  210000
    using  namespace  std;
    typedef  double  LL;
    struct  node
    {
    	int  l,r;//左右儿子
    	LL  d,dx2,dxy,dx,dy,lx,ly;//d后面跟的就是维护的数值
    	int  tl,tr;//维护区间
    	bool  qin;//这个区间是否有被初始化过
    }tr[NN];int  len;
    LL  a[N],b[N];
    inline  void  pushup(int  x)
    {
    	int  lc=tr[x].l,rc=tr[x].r;
    	tr[x].dx=tr[lc].dx+tr[rc].dx;tr[x].dy=tr[lc].dy+tr[rc].dy;
    	tr[x].dxy=tr[lc].dxy+tr[rc].dxy;tr[x].dx2=tr[lc].dx2+tr[rc].dx2;
    }
    inline  void  pushlazy(int  x,LL  lx,LL  ly)
    {
    	tr[x].dx2+=tr[x].d*lx*lx+2*lx*tr[x].dx;
    	tr[x].dxy+=ly*tr[x].dx+lx*tr[x].dy+lx*ly*tr[x].d;
    	tr[x].dx+=lx*tr[x].d;tr[x].dy+=ly*tr[x].d;
    	tr[x].lx+=lx;tr[x].ly+=ly;
    }
    inline  void  pushqin(int  x)
    {
    	int  l=tr[x].tl,r=tr[x].tr;
    	tr[x].lx=tr[x].ly=0;
    	tr[x].dx=tr[x].dy=(l+r)*tr[x].d/2;
    	tr[x].dxy=tr[x].dx2=(LL)r*(r+1)*(2*r+1)/6-(LL)(l-1)*l*(2*l-1)/6;
    	tr[x].qin=1;
    }
    inline  void  pushdown(int  x)
    {
    	if(tr[x].qin)
    	{
    		pushqin(tr[x].l);pushqin(tr[x].r);
    		tr[x].qin=0;
    	}
    	if(tr[x].lx  ||  tr[x].ly)
    	{
    		pushlazy(tr[x].l,tr[x].lx,tr[x].ly);pushlazy(tr[x].r,tr[x].lx,tr[x].ly);
    		tr[x].lx=tr[x].ly=0;
    	}
    }
    void  bt(int  l,int  r)
    {
    	int  now=++len;
    	tr[now].d=r-l+1;tr[now].tl=l;tr[now].tr=r;
    	if(l==r)tr[now].dx=a[l],tr[now].dx2=a[l]*a[l],tr[now].dxy=a[l]*b[l],tr[now].dy=b[l];
    	else
    	{
    		int  mid=(l+r)/2;
    		tr[now].l=len+1;bt(l,mid);
    		tr[now].r=len+1;bt(mid+1,r);
    		pushup(now);
    	}
    }
    void  change1(int  now,int  l,int  r,int  ll,int  rr,LL  lx,LL  ly)/*非常单纯的修改*/
    {
    	if(l==ll  &&  r==rr){pushlazy(now,lx,ly);return  ;}
    	int  mid=(l+r)/2,lc=tr[now].l,rc=tr[now].r;
    	pushdown(now);
    	if(rr<=mid)change1(lc,l,mid,ll,rr,lx,ly);
    	else  if(mid<ll)change1(rc,mid+1,r,ll,rr,lx,ly);
    	else  change1(lc,l,mid,ll,mid,lx,ly),change1(rc,mid+1,r,mid+1,rr,lx,ly);
    	pushup(now);
    }
    void  change2(int  now,int  l,int  r,int  ll,int  rr)
    {
    	if(l==ll  &&  r==rr)
    	{
    		pushqin(now);
    		return  ;
    	}
    	int  mid=(l+r)/2,lc=tr[now].l,rc=tr[now].r;
    	pushdown(now);
    	if(rr<=mid)change2(lc,l,mid,ll,rr);
    	else  if(mid<ll)change2(rc,mid+1,r,ll,rr);
    	else  change2(lc,l,mid,ll,mid),change2(rc,mid+1,r,mid+1,rr);
    	pushup(now);
    }
    double  ans_x,ans_y,ans_xy,ans_x2;
    void  findans(int  now,int  l,int  r,int  ll,int  rr)
    {
    	if(l==ll  &&  r==rr)
    	{
    		ans_x+=tr[now].dx;ans_y+=tr[now].dy;
    		ans_xy+=tr[now].dxy;ans_x2+=tr[now].dx2;
    		return  ;
    	}
    	int  mid=(l+r)/2,lc=tr[now].l,rc=tr[now].r;
    	pushdown(now);
    	if(rr<=mid)findans(lc,l,mid,ll,rr);
    	else  if(mid<ll)findans(rc,mid+1,r,ll,rr);
    	else  findans(lc,l,mid,ll,mid),findans(rc,mid+1,r,mid+1,rr);
    }
    int  n,m;
    int  main()
    {
    	scanf("%d%d",&n,&m);
    	for(int  i=1;i<=n;i++)scanf("%lf",&a[i]);
    	for(int  i=1;i<=n;i++)scanf("%lf",&b[i]);
    	bt(1,n);
    	for(int  i=1;i<=m;i++)
    	{
    		int  type;scanf("%d",&type);
    		if(type==1)
    		{
    			int  l,r;scanf("%d%d",&l,&r);
    			ans_x=ans_y=ans_xy=ans_x2=0;
    			findans(1,1,n,l,r);
    			printf("%lf
    ",(ans_xy-ans_x*ans_y/(r-l+1))/(ans_x2-ans_x*ans_x/(r-l+1)));
    		}
    		else  if(type==2)
    		{
    			int  l,r;LL  x,y;scanf("%d%d%lf%lf",&l,&r,&x,&y);
    			change1(1,1,n,l,r,x,y);
    		}
    		else  if(type==3)
    		{
    			int  l,r;LL  x,y;scanf("%d%d%lf%lf",&l,&r,&x,&y);
    			change2(1,1,n,l,r);
    			change1(1,1,n,l,r,x,y);
    		}
    	}
    	return  0;
    }
    

    小结

    在遇到平均数的题目时们可以尝试把平均数拆开化化式子来做。

  • 相关阅读:
    centos7下mysql双主+keepalived
    Nginx 性能优化有这篇就够了!
    mysql对自增主键ID进行重新排序
    nginx 配置文件 2019-12-20
    zabbix服务端接收的数据类型,便于编写脚本向服务端提交数据
    zabbix自动注册,实现自动添加机器,减少人工干预
    zabbix企业微信告警配置教程
    websocket 连接测试端口服务是否正常代码
    mongodb Sort排序能够支持的最大内存限制为32M Plan executor error during find: FAILURE
    rabbitmq 的安装配置使用
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/13820150.html
Copyright © 2011-2022 走看看