WA on #1,2,3,4,9,10
第一颗线段树维护区间和,第二颗线段树维护平方和。
#include <bits/stdc++.h>
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
const int N=100005;
double a[N];
struct node{
int l,r;
double sum=0,tag=0;
}tr[3][4*N];//1:sum 2:sqr
void pushup1(int p)
{
tr[1][p].sum=tr[1][lc].sum+tr[1][rc].sum;
}
void pushdown1(int p)
{
if(tr[1][p].tag!=0)
{
tr[1][lc].sum+=(tr[1][lc].r-tr[1][lc].l+1)*tr[1][p].tag;
tr[1][lc].tag+=tr[1][p].tag;
tr[1][rc].sum+=(tr[1][rc].r-tr[1][rc].l+1)*tr[1][p].tag;
tr[1][rc].tag+=tr[1][p].tag;
}
tr[1][p].tag=0;
}
void build1(int p,int ln,int rn)
{
tr[1][p].l=ln,tr[1][p].r=rn,tr[1][p].sum=a[ln],tr[1][p].tag=0;
if(ln==rn)return;
int mid=(ln+rn)>>1;
build1(lc,ln,mid);
build1(rc,mid+1,rn);
pushup1(p);
}
double query1(int p,int ln,int rn)
{
if(tr[1][p].l>=ln&&tr[1][p].r<=rn)return tr[1][p].sum;
pushdown1(p);
int mid=(tr[1][p].l+tr[1][p].r)>>1;
double nsum=0;
if(ln<=mid)nsum+=query1(lc,ln,rn);
if(rn>=mid+1)nsum+=query1(rc,ln,rn);
return nsum;
}
void update1(int p,int ln,int rn,double k)
{
if(tr[1][p].l>=ln&&tr[1][p].r<=rn)
{
tr[1][p].sum+=(tr[1][p].r-tr[1][p].l+1)*k;
tr[1][p].tag+=k;
return;
}
pushdown1(p);
int mid=(tr[1][p].l+tr[1][p].r)>>1;
if(ln<=mid)update1(lc,ln,rn,k);
if(rn>=mid+1)update1(rc,ln,rn,k);
pushup1(p);
}
void pushup2(int p)
{
tr[2][p].sum=0;
if(lc<4*N)tr[2][p].sum+=tr[2][lc].sum;
if(rc<4*N)tr[2][p].sum+=tr[2][rc].sum;
}
void pushdown2(int p)
{
if(tr[2][p].tag!=0)
{
if(lc<4*N)
{
tr[2][lc].tag+=tr[2][p].tag;
tr[2][lc].sum+=(tr[2][lc].r-tr[2][lc].l+1)*tr[2][p].tag*tr[2][p].tag+2*tr[2][p].tag*query1(1,tr[2][lc].l,tr[2][lc].r);
}
if(rc<4*N)
{
tr[2][rc].tag+=tr[2][p].tag;
tr[2][rc].sum+=(tr[2][rc].r-tr[2][rc].l+1)*tr[2][p].tag*tr[2][p].tag+2*tr[2][p].tag*query1(1,tr[2][rc].l,tr[2][rc].r);
}
}
tr[2][p].tag=0;
}
void build2(int p,int ln,int rn)
{
tr[2][p].l=ln,tr[2][p].r=rn,tr[2][p].sum=a[ln]*a[ln],tr[2][p].tag=0;
if(ln==rn)return;
int mid=(ln+rn)>>1;
build2(lc,ln,mid);
build2(rc,mid+1,rn);
pushup2(p);
}
double query2(int p,int ln,int rn)
{
if(tr[2][p].l>=ln&&tr[2][p].r<=rn)return tr[2][p].sum;
pushdown2(p);
int mid=(tr[2][p].l+tr[2][p].r)>>1;
double nsum=0;
if(ln<=mid)nsum+=query2(lc,ln,rn);
if(rn>=mid+1)nsum+=query2(rc,ln,rn);
return nsum;
}
void update2(int p,int ln,int rn,double k)
{
pushdown2(p);
if(tr[2][p].l>=ln&&tr[2][p].r<=rn)
{
tr[2][p].tag+=k;
tr[2][p].sum+=(tr[2][p].r-tr[2][p].l+1)*k*k+2*k*query1(1,tr[2][p].l,tr[2][p].r);
return;
}
int mid=(tr[2][p].l+tr[2][p].r)>>1;
if(ln<=mid)update2(lc,ln,rn,k);
if(rn>=mid+1)update2(rc,ln,rn,k);
pushup2(p);
}
int n,m;
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)scanf("%lf",&a[i]);
build1(1,1,n);
build2(1,1,n);
while(m--)
{
int op;
int x,y;
double k;
scanf("%d",&op);
if(op==1)
{
scanf("%d %d %lf",&x,&y,&k);
update2(1,x,y,k);
update1(1,x,y,k);
}
else if (op==2)
{
scanf("%d %d",&x,&y);
printf("%.4lf\n",query1(1,x,y)*1.0/(y-x+1));
}
else
{
scanf("%d %d",&x,&y);
double sum=query1(1,x,y);
double aver=sum*1.0/(y-x+1);
printf("%.4lf\n",(query2(1,x,y)+aver*aver*(y-x+1)-2*aver*sum)*1.0/(y-x+1));
}
}
return 0;
}