[SDOI2017]相關分析
阿新 • • 發佈:2018-12-18
我們要求的:
展開:
所以只要用線段樹維護,,,
號操作:
號操作看做是先將元素變為再執行號操作,記得將原清除。
#include<bits/stdc++.h>
#define il inline
#define ls x<<1
#define rs x<<1|1
using namespace std;
const int N=1e5+5;
struct A{double sx,sy,sxy,sxx,tx,ty;int l,r,len,tc;}t[N*4];
double xx[N],yy[N];
il void pushup(int x){t[x].sx=t[ls].sx+t[rs].sx;t[x].sy=t[ls].sy+t[rs].sy;t[x].sxy=t[ls].sxy+t[rs].sxy;t[x].sxx=t[ls].sxx+t[rs].sxx;}
il void build(int x,int l,int r){
t[x].len=r-l+1;t[x].l=l;t[x].r=r;
if(l==r){t[x].sx=xx[l];t[x].sy=yy[l];t[x].sxy=xx[l]*yy[l];t[x].sxx=xx[l]*xx[l];return;}
int mid=l+r>>1;build(ls,l,mid);build(rs,mid+1,r);pushup(x);
}il double calc(int x){return 1.0*x*(x+1)*(2*x+1)/6.0;}
il void update1(int x,double dx,double dy){
t[x].sxy+=t[x].sx*dy+t[x].sy*dx+t[x].len*dx*dy;t[x].sxx+=t[x].sx*dx*2+t[x].len*dx*dx;
t[x].sx+=t[x].len*dx;t[x].sy+=t[x].len*dy;t[x].tx+=dx;t[x].ty+=dy;
}il void update2(int x){
t[x].sx=t[x].sy=1.0*(t[x].l+t[x].r)*t[x].len/2.0;
t[x].sxy=t[x].sxx=calc(t[x].r)-calc(t[x].l-1);
t[x].tc=1;t[x].tx=t[x].ty=0;
}il void pushdown(int x){
if(t[x].tc){update2(ls);update2(rs);t[x].tc=0;}
if(t[x].tx||t[x].ty){update1(ls,t[x].tx,t[x].ty);update1(rs,t[x].tx,t[x].ty);t[x].tx=t[x].ty=0;}
}il void add(int x,int L,int R,int dx,int dy){
if(L<=t[x].l&&t[x].r<=R) return (void)(update1(x,dx,dy));
pushdown(x);int mid=t[x].l+t[x].r>>1;
if(L<=mid) add(ls,L,R,dx,dy);if(mid<R) add(rs,L,R,dx,dy);
pushup(x);
}il void change(int x,int L,int R){
if(L<=t[x].l&&t[x].r<=R) return (void)(update2(x));
pushdown(x);int mid=t[x].l+t[x].r>>1;
if(L<=mid) change(ls,L,R);if(mid<R) change(rs,L,R);
pushup(x);
}il double qry(int x,int L,int R,int o){
if(L<=t[x].l&&t[x].r<=R){if(o==1) return t[x].sx;if(o==2) return t[x].sy;if(o==3) return t[x].sxy;if(o==4) return t[x].sxx;}
pushdown(x);int mid=t[x].l+t[x].r>>1;double res=0;
if(L<=mid) res+=qry(ls,L,R,o);if(mid<R) res+=qry(rs,L,R,o);
return res;
}int main(){
int n,m,o,l,r,dx,dy;scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%lf",&xx[i]);
for(int i=1;i<=n;++i) scanf("%lf",&yy[i]);
build(1,1,n);
while(m--){
scanf("%d%d%d",&o,&l,&r);
if(o==1){
double res1=qry(1,l,r,1),res2=qry(1,l,r,2),res3=qry(1,l,r,3),res4=qry(1,l,r,4);
double p=res3-res1*res2/(r-l+1),q=res4-res1*res1/(r-l+1);
printf("%.10lf\n",p/q);
}else{scanf("%d%d",&dx,&dy);if(o==3) change(1,l,r);add(1,l,r,dx,dy);}
}return 0;
}