



发现一次交换后,对于一个区间,单点有len(区间长度)-1/len的概率还是它自己,有1/len乘1/len1的概率变成另一个区间的任何一个数,线段树维护加法和乘法即可。
#include <stdio.h>
using namespace std;
const int maxn=400001;
struct node
{
int l,r;
double sum;
double f1,f2;
}tree[maxn*8];
double a[maxn];
double ans;
int n,q;
int read()
{
char ch=getchar();
int flag=1,x=0;
while((ch<'0'||ch>'9')&&ch!='-')
ch=getchar();
if(ch=='-')
{
flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*flag;
}
void pushup(int x)
{
tree[x].sum=tree[x*2].sum+tree[x*2+1].sum;
}
void pushdown(int x)
{
tree[x*2].sum=tree[x*2].sum*tree[x].f2+tree[x].f1*(tree[x*2].r-tree[x*2].l+1);
tree[x*2+1].sum=tree[x*2+1].sum*tree[x].f2+tree[x].f1*(tree[x*2+1].r-tree[x*2+1].l+1);
tree[x*2].f1=tree[x*2].f1*tree[x].f2+tree[x].f1,tree[x*2].f2*=tree[x].f2;
tree[x*2+1].f1=tree[x*2+1].f1*tree[x].f2+tree[x].f1,tree[x*2+1].f2*=tree[x].f2;
tree[x].f1=0,tree[x].f2=1;
}
void build(int x,int lt,int rt)
{
tree[x].l=lt,tree[x].r=rt,tree[x].f2=1;
if(lt==rt)
{
tree[x].sum=a[lt];
return;
}
int mid=(lt+rt)/2;
build(x*2,lt,mid);
build(x*2+1,mid+1,rt);
pushup(x);
}
void add(int x,double l1,double r1,int l2,int r2,double temp)//一定要开double(除法)
{
if(tree[x].l>r1||tree[x].r<l1)
return;
if(tree[x].l>=l1&&tree[x].r<=r1)
{
tree[x].sum=temp*(tree[x].r-tree[x].l+1)/((r1-l1+1)*(r2-l2+1))+tree[x].sum*(r1-l1)/(r1-l1+1);
tree[x].f1=tree[x].f1*(r1-l1)/(r1-l1+1)+temp/((r1-l1+1)*(r2-l2+1));//lazy是单点的
tree[x].f2*=(r1-l1)/(r1-l1+1);
return;
}
pushdown(x);
int mid=(tree[x].l+tree[x].r)/2;
if(mid>=l1)
add(x*2,l1,r1,l2,r2,temp);
if(mid<r1)
add(x*2+1,l1,r1,l2,r2,temp);
pushup(x);
}
void query(int x,int lt,int rt)
{
if(tree[x].l>rt||tree[x].r<lt)
return;
if(tree[x].l>=lt&&tree[x].r<=rt)
{
ans+=tree[x].sum;
return;
}
pushdown(x);
int mid=(tree[x].l+tree[x].r)/2;
if(mid>=lt)
query(x*2,lt,rt);
if(mid<rt)
query(x*2+1,lt,rt);
pushup(x);
}
int main()
{
n=read(),q=read();
int i;
for(i=1;i<=n;i++)
a[i]=read();
build(1,1,n);
for(i=1;i<=q;i++)
{
int opr;
opr=read();
if(opr==1)
{
int l1,r1,l2,r2;
l1=read(),r1=read(),l2=read(),r2=read();
ans=0;
query(1,l1,r1);
double temp1=ans;
ans=0;
query(1,l2,r2);
double temp2=ans;
add(1,l1,r1,l2,r2,temp2),add(1,l2,r2,l1,r1,temp1);
}
if(opr==2)
{
int lt,rt;
lt=read(),rt=read();
ans=0;
query(1,lt,rt);
printf("%.7lf\n",ans);
}
}
return 0;
}
浙公网安备 33010602011771号