1. 程式人生 > >[SDOI2017]相關分析

[SDOI2017]相關分析

傳送門

我們要求的aa

a=i=LR(xix)(yiy)i=LR(xix)2a=\frac{\sum\limits_{i=L}^R(x_i-\overline x)(y_i-\overline y)}{\sum\limits_{i=L}^R(x_i-\overline x)^2}

展開:

a=i=LR(xiyi+xiyyixxy)i=LR(xi22xix+x2)a=\frac{\sum\limits_{i=L}^R(x_iy_i+x_i\overline y-y_i\overline x-\overline x\overline y)}{\sum\limits_{i=L}^R(x_i^2-2x_i\overline x+\overline x^2)}

a=i=LR(xiyixy)+(RL+1)×x×y(RL+1)×y×xi=LRxi2(RL+1)×2x2+(RL+1)×x2a=\frac{\sum\limits_{i=L}^R(x_iy_i-\overline x\overline y)+(R-L+1)\times\overline x\times\overline y-(R-L+1)\times\overline y\times\overline x}{\sum\limits_{i=L}^Rx_i^2-(R-L+1)\times2\overline x^2+(R-L+1)\times\overline x^2}

a=i=LRxiyi(RL+1)×xyi=LRxi2(RL+1)×x2a=\frac{\sum\limits_{i=L}^Rx_iy_i-(R-L+1)\times\overline x\overline y}{\sum\limits_{i=L}^Rx_i^2-(R-L+1)\times\overline x^2}

所以只要用線段樹維護

x\sum xy\sum yx2\sum x^2xy\sum xy

22號操作:

i=LR(xi+Δx)(yI+Δy)\sum\limits_{i=L}^R(x_i+\Delta x)(y_I+\Delta y) =i=LR(xiyi+Δxyi+Δyxi+ΔxΔy)=\sum\limits_{i=L}^R(x_iy_i+\Delta xy_i+\Delta yx_i+\Delta x\Delta y) =i=LRxiyi+i=LRyiΔx+i=LRxiΔy+(RL+1)×ΔxΔy=\sum\limits_{i=L}^Rx_iy_i+\sum\limits_{i=L}^Ry_i\Delta x+\sum\limits_{i=L}^Rx_i\Delta y+(R-L+1)\times\Delta x\Delta y

33號操作看做是先將元素變為ii再執行22號操作,記得將原tagtag清除。

#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;
}