#include<bits/stdc++.h>
#include<ctime>
#include<cstdlib>
using namespace std;
int random(int n){
return (long long)rand()*rand()%n;
}
int main(){
freopen("score1.in","w",stdout);
srand((unsigned)time(0));
int n=random(100000)+1;
int m=random(100000)+1;
cout<<n<<' '<<m<<'\n';
for(int i=1;i<=n;i++){
int a=random(101);
cout<<a<<' ';
}
cout<<'\n';
for(int i=1;i<=m;i++){
int op=random(4)+1,x=random(n)+1,y=random(n)+1,c=random(10)+1;
cout<<op<<' '<<x<<' ';
if(op>2) cout<<y<<'\n';
if(op==1) cout<<y<<' '<<c<<'\n';
if(op==2) cout<<c<<'\n';
}
}
#include<bits/stdc++.h>
#define int long long
#define mid ((l+r)>>1)
#define lt (root<<1)
#define rt (root<<1|1)
using namespace std;
const int N=1e5+5;
int n,m,a[N];
struct Node{
int sum,maxx,minn,add,l,r;
}tree[N];
inline void pushup(int root){
tree[root].sum=tree[lt].sum+tree[rt].sum;
tree[root].maxx=max(tree[lt].maxx,tree[rt].maxx);
tree[root].minn=min(tree[lt].minn,tree[rt].minn);
}
inline void pushdown(int root){
if(tree[root].add){
tree[lt].sum=tree[lt].sum+(tree[lt].r-tree[lt].l+1)*tree[root].add;
tree[rt].sum=tree[rt].sum+(tree[rt].r-tree[rt].l+1)*tree[root].add;
tree[lt].maxx+=tree[root].add;
tree[lt].minn+=tree[root].add;
tree[rt].maxx+=tree[root].add;
tree[rt].minn+=tree[root].add;
tree[lt].add+=tree[root].add;
tree[rt].add+=tree[root].add;
}
tree[root].add=0;
}
inline void build(int root,int l,int r){
tree[root].l=l;
tree[root].r=r;
if(l==r){
tree[root].sum=tree[root].maxx=tree[root].minn=a[l];
return;
}
build(lt,l,mid);
build(rt,mid+1,r);
pushup(root);
}
inline void update(int root,int l,int r,int ql,int qr,int add){
if(l>=ql&&r<=qr){
tree[root].sum+=(r-l+1)*add;
tree[root].maxx+=add;
tree[root].minn+=add;
tree[root].add+=add;
return;
}
pushdown(root);
if(ql<=mid) update(lt,l,mid,ql,qr,add);
if(qr>mid) update(rt,mid+1,r,ql,qr,add);
pushup(root);
}
inline void change(int root,int l,int r,int q,int add){
if(l==r){
tree[root].sum+=add;
tree[root].maxx+=add;
tree[root].minn+=add;
return;
}
pushdown(root);
if(q<=mid) change(lt,l,mid,q,add);
else change(rt,mid+1,r,q,add);
pushup(root);
}
inline int query_max(int root,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr) return tree[root].maxx;
pushdown(root);
int res=LONG_LONG_MIN;
if(ql<=mid) res=max(res,query_max(lt,l,mid,ql,qr));
if(qr>mid) res=max(res,query_max(rt,mid+1,r,ql,qr));
pushup(root);
return res;
}
inline int query_min(int root,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr) return tree[root].minn;
pushdown(root);
int res=LONG_LONG_MAX;
if(ql<=mid) res=min(res,query_min(lt,l,mid,ql,qr));
if(qr>mid) res=min(res,query_min(rt,mid+1,r,ql,qr));
pushup(root);
return res;
}
inline int query_sum(int root,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr) return tree[root].sum;
pushdown(root);
int res=0;
if(ql<=mid) res+=query_sum(lt,l,mid,ql,qr);
if(qr>mid) res+=query_sum(rt,mid+1,r,ql,qr);
pushup(root);
return res;
}
signed main(){
freopen("score1.in","r",stdin);
freopen("score1.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",a+i);
build(1,1,n);
while(m--){
int op,x,y,c;
scanf("%lld",&op);
if((op&1)&&!(op&2)){
scanf("%lld%lld%lld",&x,&y,&c);
if(x>y) swap(x,y);
update(1,1,n,x,y,c);
}
if(!(op&1)&&(op&2)){
scanf("%lld%lld",&x,&c);
change(1,1,n,x,c);
}
if((op&1)&&(op&2)){
scanf("%lld%lld",&x,&y);
if(x>y) swap(x,y);
long double ans=query_sum(1,1,n,x,y)*1.0/(1.0*(y-x+1));
printf("%.2Lf\n",ans);
}
if(!(op&1)&&!(op&2)){
scanf("%lld%lld",&x,&y);
if(x>y) swap(x,y);
printf("%lld\n",query_max(1,1,n,x,y)-query_min(1,1,n,x,y));
}
}
}