线段树.维护四个值: ∑x,∑y,∑xy,∑x2
3操作拆分成一个赋值操作外加一个2操作就行了。预处理一下平方和之类的就好了。
注意几个问题:
1.不要用long long(会爆long long),要用double.
2.最后是把2,3操作的lazy标记分开写。处理3标记时,直接清空2标记.
贴个代码:
#include
#include
using namespace std;
#define MAXN 105000
//#define LL long long
#define ls (p<<1)
#define rs (p<<1|1)
void _r(int& x,bool f=0)
{
char c=getchar();
while(c<'0'||c>'9')
{
f|=(c=='-');
c=getchar();
}
for(x=0;c>='0'&&c<='9';c=getchar())
{
x=(x<<1)+(x<<3)+c-'0';
}
x=f?-x:x;
return ;
}
double vx[MAXN<<2],vy[MAXN<<2],vxx[MAXN<<2],vxy[MAXN<<2],tx[MAXN<<2],ty[MAXN<<2],ti[MAXN<<2],x_2[MAXN],x_1[MAXN];
int x[MAXN],y[MAXN];
int n,m;
void merge(int p,int l,int r)
{
vx[p]=vx[l]+vx[r];
vy[p]=vy[l]+vy[r];
vxx[p]=vxx[l]+vxx[r];
vxy[p]=vxy[l]+vxy[r];
return ;
}
void build(int p,int l,int r)
{
if(l==r)
{
vx[p]=x[l];
vy[p]=y[l];
vxx[p]=1ll*x[l]*x[l];
vxy[p]=1ll*x[l]*y[l];
return ;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
merge(p,ls,rs);
return ;
}
void up1(int p,int l,int r)
{
vx[p]=vy[p]=x_1[r]-x_1[l-1];
vxx[p]=vxy[p]=x_2[r]-x_2[l-1];
ti[p]=1;
tx[p]=ty[p]=0;
return ;
}
void up2(int p,int l,int r,double dx,double dy)
{
tx[p]+=dx;
ty[p]+=dy;
vxy[p]+=vx[p]*dy+vy[p]*dx+dx*dy*1.0*(r-l+1);
vxx[p]+=vx[p]*dx*2ll+dx*dx*1.0*(r-l+1);
vx[p]+=dx*1.0*(r-l+1);
vy[p]+=dy*1.0*(r-l+1);
return ;
}
void push(int p,int l,int r)
{
int mid=(l+r)>>1;
if(ti[p])
{
up1(ls,l,mid);
up1(rs,mid+1,r);
ti[p]=0;
}
if(tx[p]||ty[p])
{
up2(ls,l,mid,tx[p],ty[p]);
up2(rs,mid+1,r,tx[p],ty[p]);
tx[p]=ty[p]=0;
}
return ;
}
void add(int p,int l,int r,int x,int y,double dx,double dy)
{
if(l>=x&&r<=y)
{
up2(p,l,r,dx,dy);
return ;
}
push(p,l,r);
int mid=(l+r)>>1;
if(x<=mid)
{
add(ls,l,mid,x,y,dx,dy);
}
if(y>mid)
{
add(rs,mid+1,r,x,y,dx,dy);
}
merge(p,ls,rs);
return ;
}
void change(int p,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
{
up1(p,l,r);
return ;
}
push(p,l,r);
int mid=(l+r)>>1;
if(x<=mid)
{
change(ls,l,mid,x,y);
}
if(y>mid)
{
change(rs,mid+1,r,x,y);
}
merge(p,ls,rs);
}
struct node
{
double x,y,xx,xy;
node(double a=0,double b=0,double c=0,double d=0)
{
x=a;
y=b;
xx=c;
xy=d;
}
node operator + (node p)
{
return node(x+p.x,y+p.y,xx+p.xx,xy+p.xy);
}
};
node query(int p,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
{
return node(vx[p],vy[p],vxx[p],vxy[p]);
}
push(p,l,r);
int mid=(l+r)>>1;
node t=node(0.0,0.0,0.0,0.0);
if(x<=mid)
{
t=t+query(ls,l,mid,x,y);
}
if(y>mid)
{
t=t+query(rs,mid+1,r,x,y);
}
return t;
}
int main()
{
_r(n);
_r(m);
for(int i=1;i<=n;i++)
{
_r(x[i]);
x_1[i]=x_1[i-1]+1.0*i;
x_2[i]=x_2[i-1]+1.0*i*i;
}
for(int i=1;i<=n;i++)
{
_r(y[i]);
}
node p;
build(1,1,n);
for(int i=1,q,x,y,s,t;i<=m;i++)
{
_r(q);
_r(x);
_r(y);
if(q==1)
{
p=query(1,1,n,x,y);
printf("%.10lf\n",(p.xy-p.x*p.y/(y-x+1))/(p.xx-p.x*p.x/(y-x+1)));
}
if(q==2)
{
_r(s);
_r(t);
add(1,1,n,x,y,s,t);
}
if(q==3)
{
_r(s);
_r(t);
change(1,1,n,x,y);
add(1,1,n,x,y,s,t);
}
}
return 0;
}