zoukankan      html  css  js  c++  java
  • 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)

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

    [Sum = sum_{i=l}^r (i - l + 1) imes (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
    ", zi/g, mu/g);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    正则表达式 1
    14 同步 1
    14 线程属性
    14 线程状态
    14 线程
    window.location.hostname与 window.location.host 区别
    泛型 的通配符类型 extends super
    svn拷贝一个项目作为新项目
    List Collections sort
    && 和 || 逻辑运算符
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8570224.html
Copyright © 2011-2022 走看看