题意
Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度、颜色等等,进而估算出星星的距离,半径等等。Frank不仅喜欢观测,还喜欢分析观测到的数据。他经常分析两个参数之间(比如亮度和半径)是否存在某种关系。现在Frank要分析参数X与Y之间的关系。他有n组观测数据,第i组观测数据记录了x_i和y_i。他需要一下几种操作1 L,R:用直线拟合第L组到底R组观测数据。用xx表示这些观测数据中x的平均数,用yy表示这些观测数据中y的平均数,即
xx=Σx_i/(R-L+1)(L<=i<=R)
yy=Σy_i/(R-L+1)(L<=i<=R)
如果直线方程是y=ax+b,那么a应当这样计算:
a=(Σ(x_i-xx)(y_i-yy))/(Σ(x_i-xx)(x_i-xx)) (L<=i<=R)
你需要帮助Frank计算a。
2 L,R,S,T:
Frank发现测量数据第L组到底R组数据有误差,对每个i满足L <= i <= R,x_i需要加上S,y_i需要加上T。
3 L,R,S,T:
Frank发现第L组到第R组数据需要修改,对于每个i满足L <= i <= R,x_i需要修改为(S+i),y_i需要修改为(T+i)。
n,|S|,|T|<=10^5
分析
码农题。
把括号展开后维护相关信息即可。
注意会爆long long,要开double。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef double LL;
const int N=100005;
int n,m,x[N],y[N];
struct tree{LL sx,sy,s,x2;pair<LL,LL> tag1,tag2;}t[N*5];
pair<LL,LL> ori=make_pair(0,0);
LL s1,s2,s3,s4;
int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
LL get_s1(int l,int r)
{
return (LL)(l+r)*(r-l+1)/2;
}
LL get_s2(int l,int r)
{
l--;
return (LL)r*(r+1)*(r*2+1)/6-(LL)l*(l+1)*(l*2+1)/6;
}
void updata(int d)
{
t[d].sx=t[d*2].sx+t[d*2+1].sx;
t[d].sy=t[d*2].sy+t[d*2+1].sy;
t[d].s=t[d*2].s+t[d*2+1].s;
t[d].x2=t[d*2].x2+t[d*2+1].x2;
}
void pushdown(int d,int L,int R)
{
if (L==R)
{
t[d].tag1=t[d].tag2=ori;
return;
}
int mid=(L+R)/2;
if (t[d].tag1!=ori)
{
LL S=t[d].tag1.first,T=t[d].tag1.second;t[d].tag1=ori;
t[d*2].tag2=t[d*2+1].tag2=ori;
t[d*2].tag1=t[d*2+1].tag1=make_pair(S,T);
int l=L,r=mid;
t[d*2].x2=get_s2(l,r)+(LL)S*S*(r-l+1)+(LL)2*S*get_s1(l,r);t[d*2].sx=get_s1(l,r)+(LL)S*(r-l+1);t[d*2].sy=get_s1(l,r)+(LL)T*(r-l+1);t[d*2].s=(LL)S*T*(r-l+1)+(LL)(S+T)*get_s1(l,r)+(LL)get_s2(l,r);
l=mid+1;r=R;
t[d*2+1].x2=get_s2(l,r)+(LL)S*S*(r-l+1)+(LL)2*S*get_s1(l,r);t[d*2+1].sx=get_s1(l,r)+(LL)S*(r-l+1);t[d*2+1].sy=get_s1(l,r)+(LL)T*(r-l+1);t[d*2+1].s=(LL)S*T*(r-l+1)+(LL)(S+T)*get_s1(l,r)+(LL)get_s2(l,r);
}
if (t[d].tag2!=ori);
{
LL S=t[d].tag2.first,T=t[d].tag2.second;t[d].tag2=make_pair(0,0);
t[d*2].tag2.first+=S;t[d*2].tag2.second+=T;
t[d*2+1].tag2.first+=S;t[d*2+1].tag2.second+=T;
int l=L,r=mid;
t[d*2].x2+=(LL)S*S*(r-l+1)+(LL)2*t[d*2].sx*S,t[d*2].s+=(LL)S*T*(r-l+1)+(LL)t[d*2].sx*T+(LL)t[d*2].sy*S;t[d*2].sx+=(LL)S*(r-l+1);t[d*2].sy+=(LL)T*(r-l+1);
l=mid+1;r=R;
t[d*2+1].x2+=(LL)S*S*(r-l+1)+(LL)2*t[d*2+1].sx*S,t[d*2+1].s+=(LL)S*T*(r-l+1)+(LL)t[d*2+1].sx*T+(LL)t[d*2+1].sy*S;t[d*2+1].sx+=(LL)S*(r-l+1);t[d*2+1].sy+=(LL)T*(r-l+1);
}
}
void build(int d,int l,int r)
{
if (l==r)
{
t[d].sx=x[l];t[d].sy=y[l];t[d].s=(LL)x[l]*y[l];t[d].x2=(LL)x[l]*x[l];
return;
}
int mid=(l+r)/2;
build(d*2,l,mid);build(d*2+1,mid+1,r);
updata(d);
}
void query(int d,int l,int r,int x,int y)
{
if (x>y) return;
pushdown(d,l,r);
if (l==x&&r==y)
{
s1+=t[d].sx;s2+=t[d].sy;s3+=t[d].s;s4+=t[d].x2;
return;
}
int mid=(l+r)/2;
query(d*2,l,mid,x,min(y,mid));
query(d*2+1,mid+1,r,max(x,mid+1),y);
}
void ins(int d,int l,int r,int x,int y,int S,int T,int op)
{
if (x>y) return;
pushdown(d,l,r);
if (l==x&&r==y)
{
if (op==2) t[d].x2+=(LL)S*S*(r-l+1)+(LL)2*t[d].sx*S,t[d].s+=(LL)S*T*(r-l+1)+(LL)t[d].sx*T+(LL)t[d].sy*S,t[d].sx+=(LL)S*(r-l+1),t[d].sy+=(LL)T*(r-l+1),t[d].tag2=make_pair(S,T);
else t[d].x2=get_s2(l,r)+(LL)S*S*(r-l+1)+(LL)2*S*get_s1(l,r),t[d].sx=get_s1(l,r)+(LL)S*(r-l+1),t[d].sy=get_s1(l,r)+(LL)T*(r-l+1),t[d].s=(LL)S*T*(r-l+1)+(LL)(S+T)*get_s1(l,r)+(LL)get_s2(l,r),t[d].tag1=make_pair(S,T);
return;
}
int mid=(l+r)/2;
ins(d*2,l,mid,x,min(y,mid),S,T,op);
ins(d*2+1,mid+1,r,max(x,mid+1),y,S,T,op);
updata(d);
}
int main()
{
n=read();m=read();
for (int i=1;i<=n;i++) x[i]=read();
for (int i=1;i<=n;i++) y[i]=read();
build(1,1,n);
while (m--)
{
int op=read(),l=read(),r=read();
if (op==1)
{
s1=0;s2=0;s3=0;s4=0;
query(1,1,n,l,r);
double xx=(double)s1/(r-l+1),yy=(double)s2/(r-l+1);
double ans1=s3-yy*s1-xx*s2+(r-l+1)*xx*yy;
double ans2=s4-(double)2*xx*s1+(double)(r-l+1)*xx*xx;
printf("%.10lf\n",ans1/ans2);
}
else
{
int s=read(),t=read();
ins(1,1,n,l,r,s,t,op);
}
}
return 0;
}