luogu P3707 [SDOI2017]相关分析

传送门

对于题目要求的东西,考虑拆开懒得拆了 ,可以发现有\(\sum x\sum y\sum x^2\sum xy\)四个变量影响最终结果,考虑维护这些值

下面记\(l,r\)为区间两端点

首先是区间加操作,可以这样维护$$\sum(x+s)=\sum x+(r-l+1)s$$$$\sum(y+s)=\sum y+(r-l+1)s$$$$\sum(x+s)^2=\sum x^2+2s\sum x+(r-l+1)s^2$$$$\sum(x+s)(y+t)=\sum xy+s\sum y+t\sum x+(r-l+1)st$$

然后是区间修改,区间修改可以看做先把所有\(x_i,y_i\)变成\(i\),然后再是区间加\((s,t)\)的操作,至于修改的话,用上平方和公式就很吼辣\(\sum_{i=1}^n i^2=\frac{n(n+1)(2n+1)}{6}\)

于是会修改成这样$$\sum x=\sum y=(r-l+1)(l+r)/2$$$$\sum x^2=\sum xy=\sum_{i=1}^r i2-\sum_{i=1} i^2$$

然后求出询问区间的上述四个值,代入你所求的公式就行了

#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double
#define eps (1e-5)

using namespace std;
const int N=120000+10;
il LL rd()
{
  LL x=0,w=1;char ch=0;
  while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
  while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
  return x*w;
}
struct node
{
  db x,y,xx,xy;
  node(){x=y=xx=xy=0;}
  node operator + (const node &b) const
  {
    node an,a=*this;
    an.x=a.x+b.x,an.y=a.y+b.y,an.xx=a.xx+b.xx,an.xy=a.xy+b.xy;
    return an;
  }
}tr[N<<2],nw;
db lz[N<<2][3],aa[N][2];
int n,m;
#define lc (o<<1)
#define rc ((o<<1)|1)
#define mid ((l+r)>>1)
il db sgmn2(db n){return n*(n+1)*(2*n+1)/6;}
il void ad(int o,int l,int r,db s,db t)
{
  db len=r-l+1;
  tr[o].xx+=s*tr[o].x*2+s*s*len;
  tr[o].xy+=s*tr[o].y+t*tr[o].x+s*t*len;
  tr[o].x+=len*s;
  tr[o].y+=len*t;
  lz[o][1]+=s,lz[o][2]+=t;
}
il void cg(int o,int l,int r)
{
  db len=r-l+1;
  lz[o][1]=lz[o][2]=0;
  tr[o].x=tr[o].y=len*(db)(l+r)/2.0;
  tr[o].xx=tr[o].xy=sgmn2(r)-sgmn2(l-1);
  lz[o][0]=1;
}
il void psdn(int o,int l,int r)
{
  if(lz[o][0]) cg(lc,l,mid),cg(rc,mid+1,r);
  ad(lc,l,mid,lz[o][1],lz[o][2]),ad(rc,mid+1,r,lz[o][1],lz[o][2]);
  lz[o][0]=lz[o][1]=lz[o][2]=0;
}
void bui(int o,int l,int r)
{
  if(l==r){tr[o].x=aa[l][0],tr[o].y=aa[l][1],tr[o].xx=tr[o].x*tr[o].x,tr[o].xy=tr[o].x*tr[o].y;return;}
  bui(lc,l,mid),bui(rc,mid+1,r);
  tr[o]=tr[lc]+tr[rc];
}
void modif1(int o,int l,int r,int ll,int rr,db s,db t)
{
  if(ll<=l&&r<=rr)
    {
      ad(o,l,r,s,t);
      //psdn(o,l,r);
      return;
    }
  psdn(o,l,r);
  if(ll<=mid) modif1(lc,l,mid,ll,rr,s,t);
  if(rr>mid) modif1(rc,mid+1,r,ll,rr,s,t);
  tr[o]=tr[lc]+tr[rc];
}
void modif2(int o,int l,int r,int ll,int rr,db s,db t)
{
  if(ll<=l&&r<=rr)
    {
      cg(o,l,r);ad(o,l,r,s,t);
      //psdn(o,l,r);
      return;
    }
  psdn(o,l,r);
  if(ll<=mid) modif2(lc,l,mid,ll,rr,s,t);
  if(rr>mid) modif2(rc,mid+1,r,ll,rr,s,t);
  tr[o]=tr[lc]+tr[rc];
}
node quer(int o,int l,int r,int ll,int rr)
{
  if(ll<=l&&r<=rr) return tr[o];
  psdn(o,l,r);
  node an;
  if(ll<=mid) an=an+quer(lc,l,mid,ll,rr);
  if(rr>mid) an=an+quer(rc,mid+1,r,ll,rr);
  tr[o]=tr[lc]+tr[rc];
  return an;
}

int main()
{
  n=rd(),m=rd();
  for(int i=1;i<=n;i++) aa[i][0]=rd();
  for(int i=1;i<=n;i++) aa[i][1]=rd();
  bui(1,1,n);
  while(m--)
    {
      int op=rd(),l=rd(),r=rd();
      if(op==1)
        {
          nw=quer(1,1,n,l,r);
          db len=r-l+1,gx=nw.x/len,gy=nw.y/len;
          printf("%.6lf\n",(nw.xy-gx*nw.y-gy*nw.x+gx*gy*len)/(nw.xx-2*gx*nw.x+gx*gx*len));
        }
      else if(op==2)
        {
          db s=rd(),t=rd();
          modif1(1,1,n,l,r,s,t);
        }
      else 
        {
          db s=rd(),t=rd();
          modif2(1,1,n,l,r,s,t);
        }
    }
  return 0;
}

posted @ 2018-11-06 20:28  ✡smy✡  阅读(126)  评论(0编辑  收藏  举报