rt,难道我写了个假的分块,感觉跑得比mn还慢。。。
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int n,m,op,l,r,bl,tot;
int id[N],L[205],R[205];
double a[N],s[205],tag[205],sq[205],k;
inline void update (int l,int r,double k){
if (id[l]==id[r]){
for (int i=l;i<=r;++i){
sq[id[i]]+=k*k+2*k*a[i];
a[i]+=k;s[id[i]]+=k;
}
return ;
}
for (int i=l;i<=R[id[l]];++i){
sq[id[i]]+=k*k+2*k*a[i];
a[i]+=k;s[id[i]]+=k;
}
for (int i=r;i>=L[id[r]];--i){
sq[id[i]]+=k*k+2*k*a[i];
a[i]+=k;s[id[i]]+=k;
}
for (int i=id[l]+1;i<id[r];++i){
tag[i]+=k;
}
}
inline double query1 (int l,int r){
double sum=0;
int len=r-l+1;
if (id[l]==id[r]){
for (int i=l;i<=r;++i){
sum+=a[i]+tag[id[i]];
}
return sum*1./(len);
}
for (int i=l;i<=R[id[l]];++i){
sum+=a[i]+tag[id[i]];
}
for (int i=r;i>=L[id[r]];--i){
sum+=a[i]+tag[id[i]];
}
for (int i=id[l]+1;i<id[r];++i){
sum+=s[i];
}
return sum*1./len;
}
inline double query2 (int l,int r){
double ans=0,sum=0;
int len=r-l+1;
if (id[l]==id[r]){
for (int i=l;i<=r;++i){
ans+=(a[i]+tag[id[i]])*(a[i]+tag[id[i]]);
sum+=a[i]+tag[id[i]];
}
return ans*1./len-(sum*1./len)*(sum*1./len);
}
for (int i=l;i<=R[id[l]];++i){
ans+=(a[i]+tag[id[i]])*(a[i]+tag[id[i]]);
sum+=a[i]+tag[id[i]];
}
for (int i=r;i>=L[id[r]];--i){
ans+=(a[i]+tag[id[i]])*(a[i]+tag[id[i]]);
sum+=a[i]+tag[id[i]];
}
for (int i=id[l]+1;i<id[r];++i){
ans+=(sq[i]+tag[i])*(sq[i]+tag[i]);
sum+=s[i];
}
return ans*1./len-(sum*1./len)*(sum*1./len);
}
signed main(){
// freopen ("方差.in","r",stdin);
// freopen ("方差.out","w",stdout);
scanf ("%d%d",&n,&m);
bl=(int) (sqrt (n));
tot=n/bl+(n%bl!=0);
for (int i=1;i<=n;++i)
scanf ("%lf",a+i);
for (int i=1;i<=n;++i)
id[N]=(i-1)/bl+1;
for (int i=1;i<=tot;++i){
L[i]=(i-1)*bl+1;
R[i]=i*bl;
}
R[tot]=n;
for (int i=1;i<=n;++i){
s[id[i]]+=a[i];
sq[id[i]]+=a[i]*a[i];
}
for (int i=1;i<=m;++i){
scanf ("%d%d%d",&op,&l,&r);
if (op==1){
scanf ("%lf",&k);
update (l,r,k);
}
if (op==2){
printf ("%.4lf\n",query1 (l,r));
}
if (op==3){
printf ("%.4lf\n",query2 (l,r));
}
}
return 0;
}