考虑左区间中的任意数x,令len1为左区间长度,sum1为左区间的期望和
经过操作1,x的期望会变为x*(len1-1)/len1+sum2/len2*(1/len1)
这个变化相当于y=kx+b,因此可以用线段树维护乘法和加法
要注意的是pushdown的时候子节点的加法受到父节点乘法的影响
#include<bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) #define sqr(a) (a)*(a) const int inf=0x3f3f3f3f; const int maxn=1e6+5; const int mod=1e9+7; struct NODE{ double sum,add,mul; }ST[maxn<<2]; void pushup(int rt){ ST[rt].sum=ST[rt<<1].sum+ST[rt<<1|1].sum; } void pushdown(int l,int r,int rt){ int m=l+r>>1; ST[rt<<1].sum=ST[rt].mul*ST[rt<<1].sum+(m-l+1)*ST[rt].add; ST[rt<<1].mul*=ST[rt].mul; ST[rt<<1].add=ST[rt].mul*ST[rt<<1].add+ST[rt].add; ST[rt<<1|1].sum=ST[rt].mul*ST[rt<<1|1].sum+(r-m)*ST[rt].add; ST[rt<<1|1].mul*=ST[rt].mul; ST[rt<<1|1].add=ST[rt].mul*ST[rt<<1|1].add+ST[rt].add; ST[rt].add=0;ST[rt].mul=1; } void build(int l,int r,int rt){ ST[rt].sum=ST[rt].add=0;ST[rt].mul=1; if(l==r){scanf("%lf",&ST[rt].sum);return;} int m=l+r>>1; build(l,m,rt<<1);build(m+1,r,rt<<1|1);pushup(rt); } void update_mul(int a,int b,double c,int l,int r,int rt){ if(a<=l&&b>=r){ ST[rt].sum*=c;ST[rt].mul*=c;ST[rt].add*=c;return; } pushdown(l,r,rt); int m=l+r>>1; if(a<=m)update_mul(a,b,c,l,m,rt<<1); if(b>m)update_mul(a,b,c,m+1,r,rt<<1|1); pushup(rt); } void update_add(int a,int b,double c,int l,int r,int rt){ if(a<=l&&b>=r){ ST[rt].add+=c;ST[rt].sum+=(r-l+1)*c;return; } pushdown(l,r,rt); int m=l+r>>1; if(a<=m)update_add(a,b,c,l,m,rt<<1); if(b>m)update_add(a,b,c,m+1,r,rt<<1|1); pushup(rt); } double query(int a,int b,int l,int r,int rt){ if(a<=l&&b>=r){return ST[rt].sum;} int m=l+r>>1; pushdown(l,r,rt); double ans=0; if(a<=m)ans+=query(a,b,l,m,rt<<1); if(b>m)ans+=query(a,b,m+1,r,rt<<1|1); return ans; } int main(){ int n,q;scanf("%d%d",&n,&q); build(1,n,1); for(int i=1;i<=q;i++){ int op;scanf("%d",&op); if(op==1){ int l1,r1,l2,r2;scanf("%d%d%d%d",&l1,&r1,&l2,&r2); double sum1=query(l1,r1,1,n,1),sum2=query(l2,r2,1,n,1); double len1=r1-l1+1,len2=r2-l2+1; update_mul(l1,r1,(len1-1)/len1,1,n,1); update_mul(l2,r2,(len2-1)/len2,1,n,1); update_add(l1,r1,1.0/len1*sum2/len2,1,n,1); update_add(l2,r2,1.0/len2*sum1/len1,1,n,1); }else{ int l,r;scanf("%d%d",&l,&r); printf("%.7lf ",query(l,r,1,n,1)); } } }