您的位置:首页 > 其它

[sdoi2017][bzoj4821] D2T3 相关分析

2017-04-15 20:27 453 查看
4821

就是维护回归方程

a=sigma(xy)-n_x_y/sigma(x^2)-n_x^2

发现等差数列有点难写,所以将每个位置上的数变换为i+x i+y形式,然后操作2变成区间加,操作3变成区间覆盖。

操作2 i+x+S i+y+T

对于xy,注意这里提到的x,y全部都是原来的x,y

(x+i)*(y+i)=xy+xi+iy+ii

(x+S+i)*(y+T+i)=xy+xT+xi+Sy+ST+Si+iy+iT+ii

增加了

xT+Sy +ST +Si+iT

Si+iT+ST可以O1,预处理出每个区间的sumi,即该区间i的和

i(S+T)+ST,分配律一下

xT+Sy

对于每一个数增加了xT+Sy

对于区间x1T+x2T+Sy1+Sy2….

T(x1+x2….)+S(y1+y2…..)

考虑维护sigma(x)and sigma(y)

T(sigma(x))+S(sigma(y))

n_x_y维护sigma(x)and sigma(y)

x+S

(i+x)^2=ii+2ix+xx

(i+x+S)^2=(i+x+S)(i+x+S)

=ii+ix+iS+xi+xx+xS+Si+Sx+SS

=ii+2ix+2iS+xx+2xS+SS

sigma(x^2)每个数增加了 2*S(i+x)+SS

2*S(sumi+sumx)

对于操作3

(x+i)*(y+i)=xy+xi+iy+ii

预处理i^2的前缀和,x,y是区间覆盖传下来的,O1处理

(i+x)^2=ii+2ix+xx

同样

所以就能O1维护了

#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#define db double
using namespace std;
int n,m;
const int N=1e5+7;
const int M=1e6+7;
bool tag[M];
double X
,Y
,xy[M],sumx[M],sumy[M],sqrx[M],tot[M],sumi[M],sqri
,add_x[M],add_y[M];
struct Pair
{
double xy,sumx,sumy,sqrx;
};
Pair operator +(Pair a,Pair b)
{
return (Pair){a.xy+b.xy,a.sumx+b.sumx,a.sumy+b.sumy,a.sqrx+b.sqrx};
}
inline void updata(int k)
{
int l=k<<1,r=k<<1|1;
xy[k]=xy[l]+xy[r];
sumx[k]=sumx[l]+sumx[r];
sumy[k]=sumy[l]+sumy[r];
sqrx[k]=sqrx[l]+sqrx[r];
}
inline void build(int k,int l,int r)
{
int mid=l+r>>1;
tot[k]=r-l+1;
sumi[k]=(l*2+tot[k]-1)*tot[k]/2;
if(l==r)
{
sumx[k]=X[l]-l;
sumy[k]=Y[l]-l;
sqrx[k]=(db)X[l]*X[l];
xy[k]=(db)X[l]*Y[l];
return;
}
build(k*2,l,mid);
build(k*2+1,mid+1,r);
updata(k);
}
inline void modify(int k,int l,int r,db S,db T)
{
tag[k]=1;
xy[k]=sumi[k]*(S+T)+(sqri[r]-sqri[l-1])+S*T*tot[k];
sumx[k]=S*tot[k];
sumy[k]=T*tot[k];
sqrx[k]=S*S*tot[k]+(sqri[r]-sqri[l-1])+2*S*sumi[k];
add_x[k]=S;
add_y[k]=T;
}
inline void uptags(int k,int L,db S,db T)
{
xy[k]+=(S+T)*sumi[k]+S*T*tot[k]+T*sumx[k]+S*sumy[k];
sqrx[k]+=S*S*tot[k]+S*2*(sumi[k]+sumx[k]);
add_x[k]+=S;
add_y[k]+=T;
sumx[k]+=tot[k]*S;
sumy[k]+=tot[k]*T;
}
inline void pushdown(int x,int L,int R)
{
int l=x<<1,r=x<<1|1,mid=L+R>>1;
if(tag[x])
{
modify(l,L,mid,add_x[x],add_y[x]);
modify(r,mid+1,R,add_x[x],add_y[x]);
add_x[x]=add_y[x]=0;
tag[x]=0;
return;
}
if(add_x[x]||add_y[x])
{
uptags(l,L,add_x[x],add_y[x]);
uptags(r,mid+1,add_x[x],add_y[x]);
add_x[x]=add_y[x]=0;
}
}
inline void cover(int k,int l,int r,int x,int y,db S,db T)
{
int mid=l+r>>1;
if(x<=l&&r<=y)
{
modify(k,l,r,S,T);
return;
}
pushdown(k,l,r);
if(x<=mid) cover(k*2,l,mid,x,y,S,T);
if(y> mid) cover(k*2+1,mid+1,r,x,y,S,T);
updata(k);
}
inline void add(int k,int l,int r,int x,int y,db S,db T)
{
int mid=l+r>>1;
if(x<=l&&r<=y)
{
uptags(k,l,S,T);
return;
}
pushdown(k,l,r);
if(x<=mid) add(k*2,l,mid,x,y,S,T);
if(y> mid) add(k*2+1,mid+1,r,x,y,S,T);
updata(k);
}
inline Pair query(int k,int l,int r,int x,int y)
{
int mid=l+r>>1;
Pair res=(Pair){0,0};
if(x<=l&&r<=y) return (Pair){xy[k],sumx[k]+sumi[k],sumy[k]+sumi[k],sqrx[k]};
pushdown(k,l,r);
if(x<=mid) res=res+query(k*2,l,mid,x,y);
if(y> mid) res=res+query(k*2+1,mid+1,r,x,y);
return res;
}
int main()
{
//  freopen("relative.in","r",stdin);
//  freopen("relative.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;i++)scanf("%lf",&X[i]);
for(int i=1;i<=n;i++)scanf("%lf",&Y[i]);
for(int i=1;i<=n;++i) sqri[i]+=sqri[i-1]+(db)i*i;
build(1,1,n);
int flag;
double len,l,r,S,T;
Pair k;
for(int i=1;i<=m;++i)
{
scanf("%d%lf%lf",&flag,&l,&r);
if(flag==1)
{
k=query(1,1,n,l,r);
len=r-l+1;
printf("%.10lf\n",(k.xy-k.sumx*k.sumy/(db)len)/(k.sqrx-k.sumx*k.sumx/(db)len));
}
if(flag==2)
{
scanf("%lf%lf",&S,&T);
add(1,1,n,l,r,S,T);
}
if(flag==3)
{
scanf("%lf%lf",&S,&T);
cover(1,1,n,l,r,S,T);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: