P2221 [HAOI2012]高速公路

题目描述

Y901高速公路是一条重要的交通纽带,*部门建设初期的投入以及使用期间的养护费用都不低,因此*在这条高速公路上设立了许多收费站。

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

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

无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开车在这条高速路上行驶时想到了这样一个问题:对于给定的l,r(l<r),在第l个到第r个收费站里等概率随机取出两个不同的收费站a和b,那么从a行驶到b将期望花费多少费用呢?

输入输出格式

输入格式:

第一行2个正整数N,M,表示有N个收费站,M次调整或询问

接下来M行,每行将出现以下两种形式中的一种

C l r v 表示将第l个收费站到第r个收费站之间的所有道路的通行费全部增加v

Q l r 表示对于给定的l,r,要求回答小A的问题

所有C与Q操作中保证1<=l<r<=N

输出格式:

对于每次询问操作回答一行,输出一个既约分数

若答案为整数a,输出a/1

输入输出样例

输入样例#1: 复制
4 5
C 1 4 2
C 1 2 -1
Q 1 2
Q 2 4
Q 1 4
输出样例#1: 复制
1/1
8/3
17/6




题意:两点之间区间和的期望值

P2221 [HAOI2012]高速公路

P2221 [HAOI2012]高速公路

非常好的线段树题

注意 (r-i+1)*(i-l+1) 这个公式之前cf有题用到过


学会了维护
P2221 [HAOI2012]高速公路
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define pb push_back
#define inf 0x3f3f3f3f
#define pb push_back
#define CLR(A,v)  memset(A,v,sizeof A)
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
typedef pair<int,int>pii;
//////////////////////////////////
const int N=1e6+5;

ll t1[N<<2],t2[N<<2],t3[N<<2],sum2[N<<2],sum3[N<<2],col[N<<2];
ll ans1,ans2,ans3;

void up(ll pos)
{
    t1[pos]=t1[pos<<1]+t1[pos<<1|1];t2[pos]=t2[pos<<1]+t2[pos<<1|1];t3[pos]=t3[pos<<1]+t3[pos<<1|1];
}
void down(ll m,ll pos)
{
    if(col[pos])
    {
        col[pos<<1]+=col[pos];col[pos<<1|1]+=col[pos];
        t1[pos<<1]+=(m-(m>>1))*col[pos];t1[pos<<1|1]+=(m>>1)*col[pos];
        t2[pos<<1]+=col[pos]*sum2[pos<<1];t2[pos<<1|1]+=col[pos]*sum2[pos<<1|1];
        t3[pos<<1]+=col[pos]*sum3[pos<<1];t3[pos<<1|1]+=col[pos]*sum3[pos<<1|1];
        col[pos]=0;
    }
}
void build(ll l,ll r,ll pos)
{
    if(l==r){sum2[pos]=l;sum3[pos]=l*l;return;}
    int m=(l+r)>>1;build(lson);build(rson);
    sum2[pos]=sum2[pos<<1]+sum2[pos<<1|1];
    sum3[pos]=sum3[pos<<1]+sum3[pos<<1|1];
}
void upsum(ll L,ll R,ll v,ll l,ll r,ll pos)
{
    if(L<=l&&r<=R){ t1[pos]+=(r-l+1)*v; t2[pos]+=sum2[pos]*v;t3[pos]+=sum3[pos]*v;col[pos]+=v;return ; }
    int m=(l+r)>>1;down(r-l+1,pos);
    if(L<=m)upsum(L,R,v,lson);if(R>m)upsum(L,R,v,rson);
    up(pos);
}
void qsum(ll L,ll R,ll l,ll r,ll pos)
{
    if(L<=l&&r<=R){ ans1+=t1[pos];ans2+=t2[pos];ans3+=t3[pos];return ;  }
    int m=(l+r)>>1;down(r-l+1,pos);
    if(L<=m)qsum(L,R,lson);if(R>m)qsum(L,R,rson);up(pos);
}
ll n,m,a,b,c;
ll l,r;
char s[3];
int main()
{
    cin>>n>>m;n--;
    build(1,n,1);
    while(m--)
    {
        RS(s);cin>>l>>r;r--;
        if(s[0]=='C'){ ll c;cin>>c;;upsum(l,r,c,1,n,1); }
        else
        {
            ans1=ans2=ans3=0;
            qsum(l,r,1,n,1);
            ll x=ans1*(r-l+1-l*r)+(l+r)*ans2-ans3;
            ll y=(1+r-l+1)*(r-l+1)/2;
            ll temp=__gcd(x,y);
            printf("%lld/%lld
",x/temp,y/temp);
        }
    }
    return 0;
}