列式子:
如果把从i号收费站到i+1号收费站之间路段编号设为i。
假如查询l号收费站到r号收费站之间的期望值。
$ Ans_{l,r} = sumlimits_{i=l}^{r-1} v_i imes (r-i) imes (i-l+1) $
$ = sumlimits_{i=l}^{r-1} v_i imes (r imes i - r imes l + r - i^2 + i imes l - i) $
$ = sumlimits_{i=l}^{r-1} v_i imes ( - i^2 + (r + l -1) imes i + r - r imes l) $
我们在线段树里维护$ sum (i^2 imes v_i) $、$ sum (i imes v_i) $、$ sum v_i $
有公式:$ sumlimits_{i=1}^{n} i^2 = frac{n imes (n+1) imes (2 imes n + 1)}{6} $
然后什么东西都好办了。
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; const int maxn=1e5+10; int n,m; long long aa,ff;char cc; long long read() { aa=0;cc=getchar();ff=1; while(cc<'0'||cc>'9') { if(cc=='-') ff=-1; cc=getchar(); } while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); return aa*ff; } long long gcd(long long x,long long y) { return y==0? x:gcd(y,x%y); } struct Node{ long long l,r,pf,yc,lc,laz; }node[4*maxn]; void bld(int pos,long long l,long long r) { node[pos].l=l;node[pos].r=r; if(l==r) return; long long mid=(node[pos].l+node[pos].r)>>1; bld(pos<<1,l,mid); bld(pos<<1|1,mid+1,r); } long long f(long long t) { return t*(t+1)/2*(2*t+1)/3; } void ud(int pos) { long long v=node[pos].laz; long long l=node[pos].l,r=node[pos].r; if(!v) return ; node[pos].lc+=(r-l+1)*v; node[pos].yc+=(l+r)*(r-l+1)/2*v; node[pos].pf+=(f(r)-f(l-1))*v; if(node[pos].l!=node[pos].r) { node[pos<<1].laz+=v; node[pos<<1|1].laz+=v; } node[pos].laz=0; } void chge(int pos,long long l,long long r,long long v) { ud(pos); if(node[pos].l==l&&node[pos].r==r) { node[pos].laz+=v; return; } node[pos].lc+=(r-l+1)*v; node[pos].yc+=(l+r)*(r-l+1)/2*v; node[pos].pf+=(f(r)-f(l-1))*v; long long mid=(node[pos].l+node[pos].r)>>1; if(r<=mid) chge(pos<<1,l,r,v); else if(l>mid) chge(pos<<1|1,l,r,v); else chge(pos<<1,l,mid,v),chge(pos<<1|1,mid+1,r,v); } long long q(int pos,long long l,long long r,long long x,long long y) { ud(pos); if(node[pos].l==l&&node[pos].r==r) return node[pos].lc*(y-y*x)+(y+x-1)*node[pos].yc-node[pos].pf; long long mid=(node[pos].l+node[pos].r)>>1; if(r<=mid) return q(pos<<1,l,r,x,y); else if(l>mid) return q(pos<<1|1,l,r,x,y); else return q(pos<<1,l,mid,x,y)+q(pos<<1|1,mid+1,r,x,y); } int main() { n=read();m=read(); long long l,r,ans,x,y;char op; bld(1,1,n-1); for(int i=1;i<=m;++i) { do op=getchar();while(op<'C'||op>'Q'); l=read();r=read(); if(op=='C') chge(1,l,r-1,read()); else { ans=q(1,l,r-1,l,r); x=r-l+1; x=x*(x-1)/2; y=gcd(ans,x); ans/=y;x/=y; printf("%lld/%lld ",ans,x); } } return 0; }