拆开柿子之后 发现要维护
∑xi
,
∑yi
,
∑x2i
,
∑xi∗yi
直接线段树就好了 两个标记合并的时候要注意下 一种可以覆盖另一种
似乎神犇有更短更快的方法?
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef double ld;
const int N=100005;
inline ld sum(int l,int r){ return (ld)(l+r)*(r-l+1)/2.0; }
inline ld sum2(int n){ return (ld)n*(n+1)*(2*n+1)/6.0; }
inline ld sum2(int l,int r){ return sum2(r)-sum2(l-1); }
int n,m;
ld _x[N],_y[N];
ld sx[N<<2],sy[N<<2],xy[N<<2],x2[N<<2];
ld f[N<<2],a[N<<2],b[N<<2],c[N<<2],d[N<<2];
inline void upd(int x){
sx[x]=sx[x<<1]+sx[x<<1|1],sy[x]=sy[x<<1]+sy[x<<1|1];
xy[x]=xy[x<<1]+xy[x<<1|1],x2[x]=x2[x<<1]+x2[x<<1|1];
}
inline void Build(int x,int l,int r){
if (l==r){
sx[x]=_x[l],sy[x]=_y[l],xy[x]=_x[l]*_y[l],x2[x]=_x[l]*_x[l]; return;
}
int mid=(l+r)>>1;
Build(x<<1,l,mid); Build(x<<1|1,mid+1,r);
upd(x);
}
inline void mark(int x,int l,int r,ld _a,ld _b,ld _c,ld _d){
f[x]=1; a[x]=_a; b[x]=_b; c[x]=_c; d[x]=_d;
sx[x]=_a*sum(l,r)+_b*(r-l+1),sy[x]=_c*sum(l,r)+_d*(r-l+1);
x2[x]=_a*_a*sum2(l,r)+2*_a*_b*sum(l,r)+_b*_b*(r-l+1);
xy[x]=_a*_c*sum2(l,r)+(_b*_c+_a*_d)*sum(l,r)+_b*_d*(r-l+1);
}
inline void mark(int x,int l,int r,ld dx,ld dy){
x2[x]+=2*sx[x]*dx+dx*dx*(r-l+1);
xy[x]+=dx*sy[x]+dy*sx[x]+dx*dy*(r-l+1);
sx[x]+=(r-l+1)*dx,sy[x]+=(r-l+1)*dy;
b[x]+=dx,d[x]+=dy; if (!f[x]) f[x]=2;
}
inline void push(int x,int l,int r){
if (!f[x]) return;
int mid=(l+r)>>1;
if (f[x]==1){
mark(x<<1,l,mid,a[x],b[x],c[x],d[x]),mark(x<<1|1,mid+1,r,a[x],b[x],c[x],d[x]);
}else if (f[x]==2){
mark(x<<1,l,mid,b[x],d[x]),mark(x<<1|1,mid+1,r,b[x],d[x]);
}
f[x]=a[x]=b[x]=c[x]=d[x]=0;
}
inline void Add(int x,int l,int r,int ql,int qr,ld dx,ld dy){
if (ql<=l && r<=qr){
mark(x,l,r,dx,dy); return;
}
push(x,l,r); int mid=(l+r)>>1;
if (ql<=mid) Add(x<<1,l,mid,ql,qr,dx,dy);
if (qr>mid) Add(x<<1|1,mid+1,r,ql,qr,dx,dy);
upd(x);
}
inline void Modify(int x,int l,int r,int ql,int qr,ld a,ld b,ld c,ld d){
if (ql<=l && r<=qr){
mark(x,l,r,a,b,c,d); return;
}
push(x,l,r); int mid=(l+r)>>1;
if (ql<=mid) Modify(x<<1,l,mid,ql,qr,a,b,c,d);
if (qr>mid) Modify(x<<1|1,mid+1,r,ql,qr,a,b,c,d);
upd(x);
}
ld SX,SY,X2,XY;
inline void Query(int x,int l,int r,int ql,int qr){
if (ql<=l && r<=qr){
SX+=sx[x]; SY+=sy[x]; X2+=x2[x]; XY+=xy[x]; return;
}
push(x,l,r); int mid=(l+r)>>1;
if (ql<=mid) Query(x<<1,l,mid,ql,qr);
if (qr>mid) Query(x<<1|1,mid+1,r,ql,qr);
}
int main(){
int order,l,r; double a,b;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
scanf("%d%d",&n,&m);
double tt;
for (int i=1;i<=n;i++) scanf("%lf",&tt),_x[i]=tt;
for (int i=1;i<=n;i++) scanf("%lf",&tt),_y[i]=tt;
Build(1,1,n);
while (m--){
scanf("%d%d%d",&order,&l,&r);
if (order==1){
SX=SY=X2=XY=0;
Query(1,1,n,l,r);
printf("%.10lf\n",(double)((XY-SX*SY/(r-l+1))/(X2-SX*SX/(r-l+1))));
}else if (order==2){
scanf("%lf%lf",&a,&b);
Add(1,1,n,l,r,a,b);
}else if (order==3){
scanf("%lf%lf",&a,&b);
Modify(1,1,n,l,r,1,a,1,b);
}
}
return 0;
}