[HAOI2012]高速公路 [线段树 期望]

[HAOI2012]高速公路

bzoj2752 luogu2221

Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用。高速路刚建成时所有的路段都是免费的。

政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价。

无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开车在这条高速路上行驶时想到了这样一个问题:对于给定的l,r(l

一条链 每次询问区间\([l,r]\)中期望花费

区间\([l,r]\)的期望花费 即一个平均值\(\begin{align*}\frac{\sum_{i=l}^r\sum_{j=i}^rdis[i][j]}{{r-l+1\choose 2}}\end{align*}\) (因为\(dis[i][j],(i>j)\)的情况和\((i的情况是一样的 求平均值 就不用再多算一遍了

考虑第\(i\)条边的贡献 它总共在\((i-l+1)(r-i+1)\)个区间内 所以化简为\(\sum_iw[i](i-l+1)(r-i+1)\)

我将\(w[i]\)表示\(i-1\to i\)的道路花费 所以第\(i\)条边在区间\([l,r]\)内贡献了 \(w[i]*(i-l+1)(r-i)=w[i]* i *(l+r-1)-w[i]*i^2+r*(1-l)\)

即线段树\(\sum w[i]*i,\sum w[i]*i^2,\sum w[i]\)

然后注意一些小细节就好 对,注意\(l*l\)要爆int QAQ

struct node{ll sum1,sum2,sum3,add,pre1,pre2;}t[N<<2];
void pup(int o){
    t[o].sum1=t[ls].sum1+t[rs].sum1,t[o].sum2=t[ls].sum2+t[rs].sum2,t[o].sum3=t[ls].sum3+t[rs].sum3;
}
void updnode(int o,int l,int r,ll k){
    t[o].sum1+=k*t[o].pre1,t[o].sum2+=k*t[o].pre2,t[o].sum3+=((ll)r-l+1)*k,t[o].add+=k;
}
void pudw(int o,int l,int r){
    if(!t[o].add) return;
    int mid=l+r>>1;
    updnode(ls,l,mid,t[o].add),updnode(rs,mid+1,r,t[o].add),t[o].add=0;
}
void upd(int o,int l,int r,int x,int y,ll k){
    if(x>r||y>1;
    upd(ls,l,mid,x,y,k),upd(rs,mid+1,r,x,y,k);
    pup(o);
}
ll d,ans1,ans2,sum1,sum2,sum3;
void query(int o,int l,int r,int x,int y){
    if(x>r||y>1;
    query(ls,l,mid,x,y),query(rs,mid+1,r,x,y);
    pup(o);
    
}
void build(int o,int l,int r){
    if(l==r){t[o]=(node){0,0,0,0,l,(ll)l*l};return;}
    int mid=l+r>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    t[o].pre1=t[ls].pre1+t[rs].pre1,t[o].pre2=t[ls].pre2+t[rs].pre2;
}
ll gcd(ll x,ll y){return !y?x:gcd(y,x%y);}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
    rd(n),rd(m);
    char opt[5];
    build(1,1,n);
    for(int i=1,x,y,k;i<=m;++i){
        scanf("%s",opt);rd(x),rd(y),--y;
        if(opt[0]=='C'){
            rd(k);
            upd(1,1,n,x,y,(ll)k);
        }
        else{
            sum1=sum2=sum3=0ll;query(1,1,n,x,y);++y;
            ans1=sum1*((ll)y+x-1)-sum2+(ll)y*(1-x)*sum3,ans2=((ll)y-x)*((ll)y-x+1)/2;
            d=gcd(ans1,ans2),ans1/=d,ans2/=d;
            if(!ans1) puts("0/1");
            else printf("%lld/%lld\n",ans1,ans2);
        }
    }
    return 0; 
}

你可能感兴趣的:([HAOI2012]高速公路 [线段树 期望])