BZOJ 2752: [HAOI2012]高速公路(road) 线段树
这个期望显然可以表示成总价值/总方案数.
然后我们用线段树依次维护 $\sum val[i]$,$\sum val[i]\times i$,$\sum val[i]\times i^2$ 即可.
code:
#include <cmath>
#include <cstdio>
#include <string>
#include <algorithm>
#define N 100006
#define ll long long
#define lson now<<1
#define rson now<<1|1
using namespace std;
namespace IO {
void setIO(string s)
{
string in=s+".in";
string out=s+".out";
freopen(in.c_str(),"r",stdin);
// freopen(out.c_str(),"w",stdout);
}
};
ll re2,re3,re4;
int n,m;
struct node {
int l,r;
ll sum[5],tag;
}s[N<<2];
void pushup(int now)
{
for(int i=0;i<5;++i)
s[now].sum[i]=s[lson].sum[i]+s[rson].sum[i];
}
void build(int l,int r,int now)
{
s[now].l=l;
s[now].r=r;
if(l==r)
{
s[now].sum[0]=l;
s[now].sum[1]=(ll)l*l;
return;
}
int mid=(l+r)>>1;
build(l,mid,lson),build(mid+1,r,rson),pushup(now);
}
void mark(int now,ll d)
{
s[now].sum[2]+=d*s[now].sum[0];
s[now].sum[3]+=(s[now].r-s[now].l+1)*d;
s[now].sum[4]+=d*s[now].sum[1];
s[now].tag+=d;
}
void pushdown(int now)
{
if(s[now].tag) mark(lson,s[now].tag),mark(rson,s[now].tag),s[now].tag=0;
}
void update(int l,int r,int now,int L,int R,int v)
{
if(l>=L&&r<=R)
{
mark(now,v);
return;
}
int mid=(l+r)>>1;
pushdown(now);
if(L<=mid) update(l,mid,lson,L,R,v);
if(R>mid) update(mid+1,r,rson,L,R,v);
pushup(now);
}
void query(int l,int r,int now,int L,int R)
{
if(l>=L&&r<=R)
{
re2+=s[now].sum[2];
re3+=s[now].sum[3];
re4+=s[now].sum[4];
return;
}
int mid=(l+r)>>1;
pushdown(now);
if(L<=mid) query(l,mid,lson,L,R);
if(R>mid) query(mid+1,r,rson,L,R);
}
int main()
{
// IO::setIO("input");
int i,j;
scanf("%d%d",&n,&m),--n;
build(1,n,1);
for(i=1;i<=m;++i)
{
char op[3];
scanf("%s",op);
if(op[0]=='C')
{
int l,r,v;
scanf("%d%d%d",&l,&r,&v);
--r;
update(1,n,1,l,r,v);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
--r;
re2=re3=re4=0;
query(1,n,1,l,r);
ll up=(r+l)*re2+(ll)(r-(ll)r*l-l+1)*re3-re4;
ll dw=(ll)(r-l+2)*(r-l+1)/2;
ll g=__gcd(up,dw);
up/=g,dw/=g;
printf("%lld/%lld\n",up,dw);
}
}
return 0;
}

浙公网安备 33010602011771号