推式子
实数读入就别用整数的快读了。。
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int read()
{
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return f*x;
}
const int N=1e5+5;
const double eps=1e-6;
int n,m,f,a,b;
double c[N],sum1[N*4],sum2[N*4],k,add[N*4],s;
void build(int k,int l,int r)
{
if(l==r)
{
sum1[k]=c[l];
sum2[k]=c[l]*c[l];
return;
}
int mid=(l+r)/2;
build(k*2,l,mid);
build(k*2+1,mid+1,r);
sum1[k]=sum1[k*2]+sum1[k*2+1];
sum2[k]=sum2[k*2]+sum2[k*2+1];
}
void update(int k,int l,int r,double v)
{
add[k]+=v;
sum2[k]+=2*v*sum1[k]+(r-l+1)*v*v;
sum1[k]+=(r-l+1)*v;
}
void pushdown(int k,int l,int r,int mid)
{
if(fabs(add[k])<eps) return;
update(k*2,l,mid,add[k]);
update(k*2+1,mid+1,r,add[k]);
add[k]=0;
}
void change(int k,int l,int r,int x,int y,double v)
{
if(l>y||r<x) return;
if(l>=x&&r<=y)
{
add[k]+=v;
sum2[k]+=2*v*sum1[k]+(r-l+1)*v*v;
sum1[k]+=(r-l+1)*v;
return;
}
int mid=(l+r)/2;
pushdown(k,l,r,mid);
change(k*2,l,mid,x,y,v);
change(k*2+1,mid+1,r,x,y,v);
sum1[k]=sum1[k*2]+sum1[k*2+1];
sum2[k]=sum2[k*2]+sum2[k*2+1];
}
double query1(int k,int l,int r,int x,int y)
{
if(l>y||r<x) return 0;
if(l>=x&&r<=y) return sum1[k];
int mid=(l+r)/2;
pushdown(k,l,r,mid);
return query1(k*2,l,mid,x,y)+query1(k*2+1,mid+1,r,x,y);
}
double query2(int k,int l,int r,int x,int y)
{
if(l>y||r<x) return 0;
if(l>=x&&r<=y) return sum2[k];
int mid=(l+r)/2;
pushdown(k,l,r,mid);
return query2(k*2,l,mid,x,y)+query2(k*2+1,mid+1,r,x,y);
}
int main()
{
n=read(); m=read();
for(int i=1;i<=n;i++) scanf("%lf",&c[i]);
build(1,1,n);
for(int i=1;i<=m;i++)
{
f=read(); a=read(); b=read();
if(f==1) {
scanf("%lf",&k);
change(1,1,n,a,b,k);
}
if(f==2) {
printf("%.4f\n",query1(1,1,n,a,b)/(b-a+1));
}
if(f==3) {
s=query1(1,1,n,a,b)/(b-a+1);
printf("%.4f\n",query2(1,1,n,a,b)/(b-a+1)-s*s);
}
}
return 0;
}