题目:
题解:
这个给的a的柿子很明显不好弄啊,我们画一画
a=∑Ri=L(x−x¯)(y−y¯)∑Ri=L(x−x¯)2
a
=
∑
i
=
L
R
(
x
−
x
¯
)
(
y
−
y
¯
)
∑
i
=
L
R
(
x
−
x
¯
)
2
(以后 ∑ ∑ 表示 ∑Ri=L ∑ i = L R )
=∑(xy−xy¯−x¯y+x¯y¯)∑(x2+x¯2−2xx¯)=∑xy−∑xy¯−∑x¯y+∑x¯y¯∑x2+∑x¯2−∑2xx¯
=
∑
(
x
y
−
x
y
¯
−
x
¯
y
+
x
¯
y
¯
)
∑
(
x
2
+
x
¯
2
−
2
x
x
¯
)
=
∑
x
y
−
∑
x
y
¯
−
∑
x
¯
y
+
∑
x
¯
y
¯
∑
x
2
+
∑
x
¯
2
−
∑
2
x
x
¯
然后再把 x¯y¯ x ¯ y ¯ 的柿子带进去
=∑xy−∑x∑yr−l+1−∑x∑yr−l+1+(r−l+1)∗∑x∑y(r−l+1)2∑x2+(∑x)2r−l+1−2(∑x)2r−l+1
=
∑
x
y
−
∑
x
∑
y
r
−
l
+
1
−
∑
x
∑
y
r
−
l
+
1
+
(
r
−
l
+
1
)
∗
∑
x
∑
y
(
r
−
l
+
1
)
2
∑
x
2
+
(
∑
x
)
2
r
−
l
+
1
−
2
(
∑
x
)
2
r
−
l
+
1
=∑xy−∑x∑yr−l+1∑x2−(∑x)2r−l+1
=
∑
x
y
−
∑
x
∑
y
r
−
l
+
1
∑
x
2
−
(
∑
x
)
2
r
−
l
+
1
那么线段树我们需要维护的值是 ∑xy,∑x,∑y,∑x2 ∑ x y , ∑ x , ∑ y , ∑ x 2
然后区间修改画画柿子就好了
然后是几个注意点:数组都开成double吧,不然炸了精度
线段树的覆盖和增加是这样的:覆盖的时候把同一层的增加抹去,增加的时候如果同一层有覆盖标记,就直接累加到覆盖标记上。这样在pushdown的时候谁先谁后就无所谓了,因为只会存在一个
代码:
#include <cstdio>
#include <cstring>
using namespace std;
const double INF=1e9;
const int N=100005;
double sumxy[N*4],sumx[N*4],sumy[N*4],sumxf[N*4],allx[N*4],ally[N*4],deltax[N*4],deltay[N*4],x[N],y[N],sxy,sx,sy,sxf;
double Sum(double x){return x*(x+1.0)/2.0;}
double Sum2(double x){return x*(x+1.0)*(2.0*x+1.0)/6.0;}
void updata(int now)
{
sumxy[now]=sumxy[now<<1]+sumxy[now<<1|1];
sumx[now]=sumx[now<<1]+sumx[now<<1|1];
sumy[now]=sumy[now<<1]+sumy[now<<1|1];
sumxf[now]=sumxf[now<<1]+sumxf[now<<1|1];
}
void pushdown(int now,int l,int r,int mid)
{
if (allx[now]!=INF || ally[now]!=INF)
{
sumxy[now<<1]=(mid-l+1.0)*allx[now]*ally[now]+(allx[now]+ally[now])*(Sum(mid)-Sum(l-1))+Sum2(mid)-Sum2(l-1);
sumx[now<<1]=(mid-l+1.0)*allx[now]+Sum(mid)-Sum(l-1);
sumy[now<<1]=(mid-l+1.0)*ally[now]+Sum(mid)-Sum(l-1);
sumxf[now<<1]=(mid-l+1.0)*allx[now]*allx[now]+Sum2(mid)-Sum2(l-1)+2.0*allx[now]*(Sum(mid)-Sum(l-1));
sumxy[now<<1|1]=(r-mid+0.0)*allx[now]*ally[now]+(allx[now]+ally[now])*(Sum(r)-Sum(mid))+Sum2(r)-Sum2(mid);
sumx[now<<1|1]=(r-mid+0.0)*allx[now]+Sum(r)-Sum(mid);
sumy[now<<1|1]=(r-mid+0.0)*ally[now]+Sum(r)-Sum(mid);
sumxf[now<<1|1]=(r-mid+0.0)*allx[now]*allx[now]+Sum2(r)-Sum2(mid)+2.0*allx[now]*(Sum(r)-Sum(mid));
allx[now<<1]=allx[now<<1|1]=allx[now];
ally[now<<1]=ally[now<<1|1]=ally[now];
allx[now]=INF; ally[now]=INF;
deltax[now<<1]=deltax[now<<1|1]=0;
deltay[now<<1]=deltay[now<<1|1]=0;
}
if (deltax[now] || deltay[now])
{
sumxf[now<<1]+=(mid-l+1.0)*deltax[now]*deltax[now]+sumx[now<<1]*2.0*deltax[now];
sumxy[now<<1]+=deltay[now]*sumx[now<<1]+deltax[now]*sumy[now<<1]+(mid-l+1.0)*deltax[now]*deltay[now];
sumx[now<<1]+=deltax[now]*(mid-l+1.0);
sumy[now<<1]+=deltay[now]*(mid-l+1.0);
if (allx[now<<1]!=INF || ally[now<<1]!=INF) allx[now<<1]+=deltax[now],ally[now<<1]+=deltay[now];
else deltax[now<<1]+=deltax[now],deltay[now<<1]+=deltay[now];
sumxf[now<<1|1]+=(r-mid+0.0)*deltax[now]*deltax[now]+sumx[now<<1|1]*2.0*deltax[now];
sumxy[now<<1|1]+=deltay[now]*sumx[now<<1|1]+deltax[now]*sumy[now<<1|1]+(r-mid+0.0)*deltax[now]*deltay[now];
sumx[now<<1|1]+=deltax[now]*(r-mid+0.0);
sumy[now<<1|1]+=deltay[now]*(r-mid+0.0);
if (allx[now<<1|1]!=INF || ally[now<<1|1]!=INF) allx[now<<1|1]+=deltax[now],ally[now<<1|1]+=deltay[now];
else deltax[now<<1|1]+=deltax[now],deltay[now<<1|1]+=deltay[now];
deltax[now]=0; deltay[now]=0;
}
}
void build(int now,int l,int r)
{
allx[now]=ally[now]=INF;
if (l==r)
{
sumxy[now]=x[l]*y[l];sumx[now]=x[l];
sumy[now]=y[l];sumxf[now]=x[l]*x[l];
return;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
updata(now);
}
void add(int now,int l,int r,int lrange,int rrange,double s,double t)
{
if (lrange<=l && rrange>=r)
{
sumxf[now]+=(r-l+1.0)*s*s+sumx[now]*2.0*s;
sumxy[now]+=t*sumx[now]+s*sumy[now]+(r-l+1.0)*s*t;
sumx[now]+=s*(r-l+1.0);sumy[now]+=t*(r-l+1.0);
if (allx[now]!=INF || ally[now]!=INF) allx[now]+=s,ally[now]+=t;
else deltax[now]+=s,deltay[now]+=t;
return;
}
int mid=(l+r)>>1;pushdown(now,l,r,mid);
if (lrange<=mid) add(now<<1,l,mid,lrange,rrange,s,t);
if (rrange>mid) add(now<<1|1,mid+1,r,lrange,rrange,s,t);
updata(now);
}
void change(int now,int l,int r,int lrange,int rrange,double s,double t)
{
if (lrange<=l && rrange>=r)
{
sumxy[now]=(r-l+1.0)*s*t+(s+t)*(Sum(r)-Sum(l-1))+Sum2(r)-Sum2(l-1);
sumx[now]=(r-l+1.0)*s+Sum(r)-Sum(l-1);
sumy[now]=(r-l+1.0)*t+Sum(r)-Sum(l-1);
sumxf[now]=(r-l+1.0)*s*s+Sum2(r)-Sum2(l-1)+2.0*s*(Sum(r)-Sum(l-1));
allx[now]=s; ally[now]=t; deltax[now]=0; deltay[now]=0;
return;
}
int mid=(l+r)>>1;pushdown(now,l,r,mid);
if (lrange<=mid) change(now<<1,l,mid,lrange,rrange,s,t);
if (rrange>mid) change(now<<1|1,mid+1,r,lrange,rrange,s,t);
updata(now);
}
void qurry(int now,int l,int r,int lrange,int rrange)
{
if (lrange<=l && rrange>=r)
{
sxy+=sumxy[now]; sx+=sumx[now]; sy+=sumy[now];
sxf+=sumxf[now];return;
}
int mid=(l+r)>>1;pushdown(now,l,r,mid);
if (lrange<=mid) qurry(now<<1,l,mid,lrange,rrange);
if (rrange>mid) qurry(now<<1|1,mid+1,r,lrange,rrange);
}
int main()
{
int n,m;scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%lf",&x[i]);
for (int i=1;i<=n;i++) scanf("%lf",&y[i]);
build(1,1,n);
while (m--)
{
int id,l,r;double s,t;
scanf("%d%d%d",&id,&l,&r);
if (id==1)
{
sxy=0;sx=0;sy=0;sxf=0;
qurry(1,1,n,l,r);
double ans=sxy-(sx*sy)*1.0/(r-l+1.0);
ans/=sxf-(sx*sx)*1.0/(r-l+1.0);
printf("%.10lf\n",ans);
}
else
{
scanf("%lf%lf",&s,&t);
if (id==2) add(1,1,n,l,r,s,t);else change(1,1,n,l,r,s,t);
}
}
}