BZOJ2752: [HAOI2012]高速公路(road)

2752: [HAOI2012]高速公路(road)

Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 1734 Solved: 684
[Submit][Status][Discuss]

Description

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将期望花费多少费用呢?

Input

第一行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

Output

对于每次询问操作回答一行,输出一个既约分数
若答案为整数a,输出a/1

Sample Input

4 5

C 1 4 2

C 1 2 -1

Q 1 2

Q 2 4

Q 1 4

Sample Output

1/1

8/3

17/6

HINT

数据规模

所有C操作中的v的绝对值不超过10000

在任何时刻任意道路的费用均为不超过10000的非负整数

所有测试点的详细情况如下表所示

Test N M

1 =10 =10

2 =100 =100

3 =1000 =1000

4 =10000 =10000

5 =50000 =50000

6 =60000 =60000

7 =70000 =70000

8 =80000 =80000

9 =90000 =90000

10 =100000 =100000

Source

题解

先把边权弄到点上,所有区间\([l,r]\)变为\([l,r-1]\)

分母是C(r - l + 2, 2)

考虑\(i\in[l,r]\)的点\(i\)对期望的贡献
分子即为

\[Sum = \sum_{i=l}^r (i - l + 1) \times (r - i + 1) \]

\[=(r - l - lr + 1) \sum_{i=l}^rv_i + (x + y)\sum_{i=l}^rv_ii-\sum_{i=l}^rv_ii^2 \]

线段树维护\(v_i,\ v_i^2, vi\)的和即可

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
inline long long max(long long a, long long b){return a > b ? a : b;}
inline long long min(long long a, long long b){return a < b ? a : b;}
inline void swap(long long &x, long long &y){long long tmp = x;x = y;y = tmp;}
inline void read(long long &x)
{
    x = 0;char ch = getchar(), c = ch;
    while(ch < '0' || ch > '9') c = ch, ch = getchar();
    while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
    if(c == '-') x = -x;
}
const long long INF = 0x3f3f3f3f3f3f3f3f;
const long long MAXN = 100000 + 10;
struct Node
{
    long long sum_i, sum_i2, sum_v, sum_vi, sum_vi2, len;
    long long add;
    Node(){sum_i = sum_i2 = sum_v = sum_vi = sum_vi2 = len = add = 0;}
}node[MAXN << 2];
Node merge(Node& a, Node& b)
{
    Node re;
    re.sum_v = a.sum_v + b.sum_v;
    re.sum_vi = a.sum_vi + b.sum_vi;
    re.sum_vi2 = a.sum_vi2 + b.sum_vi2;
    return re;
}
void pushup(long long o)
{
    Node& re = node[o], &a = node[o << 1], &b = node[o << 1 | 1];
    re.sum_v = a.sum_v + b.sum_v;
    re.sum_vi = a.sum_vi + b.sum_vi;
    re.sum_vi2 = a.sum_vi2 + b.sum_vi2;
}
void pushdown(long long o)
{
    if(node[o].add)
    {
        long long v = node[o].add;
        for(long long i = 0;i <= 1;++ i)
        {
            Node &a = node[o << 1 | i];
            a.sum_v += a.len * v;
            a.sum_vi += a.sum_i * v;
            a.sum_vi2 += a.sum_i2 * v;
            a.add += v;
        }
        node[o].add = 0;
    }
}
long long n, q;
void build(long long o = 1, long long l = 1, long long r = n)
{
    if(l == r)
    {
        node[o].sum_i = l, node[o].sum_i2 = l * l, node[o].len = 1;
        return;
    }
    long long mid = (l + r) >> 1;
    build(o << 1, l, mid);
    build(o << 1 | 1, mid + 1, r);
    node[o].len = node[o << 1].len + node[o << 1 | 1].len;
    node[o].sum_i = node[o << 1].sum_i + node[o << 1 | 1].sum_i;
    node[o].sum_i2 = node[o << 1].sum_i2 + node[o << 1 | 1].sum_i2;
}
void modify(long long ll, long long rr, long long k, long long o = 1, long long l = 1, long long r = n)
{
    if(l != r) pushdown(o);
    if(ll <= l && rr >= r) 
    {
        node[o].sum_v += k * node[o].len;
        node[o].sum_vi += k * node[o].sum_i;
        node[o].sum_vi2 += k * node[o].sum_i2;
        node[o].add += k;
        return;
    }
    long long mid = (l + r) >> 1;
    if(mid >= ll) modify(ll, rr, k, o << 1, l, mid);
    if(mid < rr) modify(ll, rr, k, o << 1 | 1, mid + 1, r);
    pushup(o);
}
Node ask(long long ll, long long rr, long long o = 1, long long l = 1, long long r = n)
{
    if(l != r) pushdown(o);
    if(ll <= l && rr >= r) return node[o];
    Node a, b, re;
    long long mid = (l + r) >> 1;
    if(mid >= ll) a = ask(ll, rr, o << 1, l, mid);
    if(mid < rr) b = ask(ll, rr, o << 1 | 1, mid + 1, r);
    pushup(o);
    re = merge(a, b);
    return re;
}
char s[10];
long long gcd(long long a, long long b)
{
    return !b ? a : gcd(b, a%b);
}
int main()
{
    read(n), read(q);
    build();
    for(long long i = 1;i <= q;++ i)
    {
        scanf("%s", s + 1);
        long long l, r, v;read(l), read(r);-- r;
        if(s[1] == 'C') read(v), modify(l, r, v);
        else
        {
            Node a = ask(l, r);
            long long zi = (r - l - l * r + 1) * a.sum_v + (l + r) * a.sum_vi - a.sum_vi2, mu = (r - l + 2) * (r - l + 1) / 2;
            long long g = gcd(zi, mu);
            printf("%lld/%lld\n", zi/g, mu/g);
        }
    }
    return 0;
}
posted @ 2018-03-14 21:20  嘒彼小星  阅读(190)  评论(0编辑  收藏  举报