rt
question:
1.输出四舍五入
2.线段树求出来的值有问题
3.已知build和update无误
#include<iostream>
using namespace std;
const int N=1e5+10;
int n,m,op,x,y,k,p;
double a[N];
struct node{
int l,r;
double lazy;
double val;
double sum;
}tree[N<<2];
double pow(double i){return i*i;};
//建树
void build(int i,int l,int r){
tree[i].l=l,tree[i].r=r,tree[i].lazy=0;
if(l==r){tree[i].val=a[l];return ;}
int mid=l+r>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
tree[i].val=tree[i<<1].val+tree[i<<1|1].val;
}
void push_down(int i){
if(!tree[i].lazy) return ;
tree[i<<1].lazy+=tree[i].lazy;
tree[i<<1|1].lazy+=tree[i].lazy;
tree[i<<1].val+=tree[i].lazy*(tree[i].r-tree[i].l+1);
tree[i<<1|1].val+=tree[i].lazy*(tree[i].r-tree[i].l+1);
tree[i].lazy=0;
}
//区间加
void update(int i,int l,int r,int k){
if(tree[i].l>r || tree[i].r<l) return ;
if(tree[i].l<l && tree[i].r>r){
tree[i].val+=(tree[i].r-tree[i].l+1)*k;
tree[i].lazy+=k;
}
push_down(i);
update(i<<1,l,r,k);
update(i<<1|1,l,r,k);
}
//方差
double query(int i,int l,int r,double p){
if(tree[i].l==tree[i].r) return pow(tree[i].val-p);
if(tree[i].l>r || tree[i].r<l) return 0;
push_down(i);
query(i<<1,l,r,p);
query(i<<1|1,l,r,p);
}
//平均值
double query_p(int i,int l,int r){
if(tree[i].l>r || tree[i].r<l) return 0;
if(tree[i].l<=l && tree[i].r>=r) return tree[i].val;
push_down(i);
query_p(i<<1,l,r);
query_p(i<<1|1,l,r);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lf",&a[i]);
build(1,1,n);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&op,&x,&y);
if(op==1) scanf("%lf",&k),update(1,x,y,k);
if(op==2) printf("%.4lf\n",query_p(1,x,y)/((y-x+1)*1.0));
if(op==3){//方差
p=query_p(1,x,y)/(y-x+1);
printf("%.4lf\n",query(1,x,y,p));
}
}
return 0;
}