题目大意:给出一个n个结点,n-1条边的链,边权初始为0;
m次操作,操作有两种:
1. C:区间[l,r]的边权加上或减去一个数;
2. Q:查询区间随机取不相同两点之间的期望长度;
题解:根据期望的定义直接计算,总状态数共 (r−l+1)∗(r−l)2 种
记
v[i]
为
(i,i+1)
的边权,其产生贡献的条件为同时选了其左边(包括i本身)和右边的点,即
v[i]∗(i−l+1)∗(r−i)
展开得到
v[i]∗(r−l∗r)+v[i]∗i∗(l+r−1)−v[i]∗i2
所以只需要维护
∑v[i],∑v[i]∗i,∑v[i]∗i∗i
,用线段树可以很方便地维护
注意修改的时候也是r-1
我的收获:线段树大法~~暴力算期望
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 100005
int n,q;
ll si[N],sii[N];//前缀和
struct node{
ll a1,a2,a3;
node(){}
node(ll _,ll __,ll ___){a1=_,a2=__,a3=___;}
};
node operator +(node x,node y){return node(x.a1+y.a1,x.a2+y.a2,x.a3+y.a3);}
struct SegmentTree{
#define ls x<<1
#define rs x<<1|1
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
#define root 1,n,1
ll len[N<<2],gas[N<<2],kel[N<<2];//for update
ll add[N<<2];//lazy-tag
ll sum[N<<2],sui[N<<2],ali[N<<2];//sum(a_i),sum(a_i*i),sum(a_i*i*i)
inline void matain(int x,long long v){add[x]+=v,sum[x]+=v*len[x];sui[x]+=v*gas[x];ali[x]+=v*kel[x];}
inline void pushdown(int x)
{
if(!add[x]) return ;
matain(ls,add[x]),matain(rs,add[x]);
add[x]=0;
}
inline void pushup(int x){sum[x]=sum[ls]+sum[rs],sui[x]=sui[ls]+sui[rs],ali[x]=ali[ls]+ali[rs];}
void build(int l,int r,int x)
{
len[x]=r-l+1;
gas[x]=si[r]-si[l-1];
kel[x]=sii[r]-sii[l-1];
if(l==r) return ;
int m=l+r>>1;
build(lson),build(rson);
}
void modify(int L,int R,int v,int l,int r,int x)
{
if(L<=l&&r<=R){matain(x,v);return ;}
pushdown(x);
int m=l+r>>1;
if(L<=m) modify(L,R,v,lson);
if(R>m) modify(L,R,v,rson);
pushup(x);
}
node query(int L,int R,int l,int r,int x)
{
if(L<=l&&r<=R) return node(sum[x],sui[x],ali[x]);
pushdown(x);
int m=l+r>>1;
if(L<=m&&R>m) return query(L,R,lson)+query(L,R,rson);
if(L<=m) return query(L,R,lson);
if(R>m) return query(L,R,rson);
}
}T;
void work()
{
int x,y,z;char opt[10];
while(q--){
scanf("%s%d%d",opt,&x,&y);
if(opt[0]=='C') scanf("%d",&z),T.modify(x,y-1,z,root);
else{
node ans=T.query(x,y-1,root);
ll fz=ans.a1*(y-1ll*x*y)+ans.a2*(x+y-1)-ans.a3;
ll fm=1ll*(y-x+1)*(y-x)/2;
ll g=__gcd(fz,fm);
printf("%lld/%lld\n",fz/g,fm/g);
}
}
}
void init()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) si[i]=si[i-1]+i,sii[i]=sii[i-1]+1ll*i*i;
T.build(root);
}
int main()
{
init();
work();
return 0;
}