bzoj 2752 [HAOI2012]高速公路(road) 线段树

Posted copperoxide

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2752 [HAOI2012]高速公路(road) 线段树相关的知识,希望对你有一定的参考价值。

题面

题目传送门

解法

先把边转化成区间

其实我们只要计算(sum_{i=l}^{r-1}sum_{j=i+1}^{r}sum(i,j))

把式子拆开,可以得到((l+r)sum w_i*i-(l+1)(r-1)sum w_i-sum w_i*i^2)

用线段树分别维护这三个值即可

时间复杂度:(O(m log n))

代码

#include <bits/stdc++.h>
#define int long long
#define N 100010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == ‘-‘) f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - ‘0‘, c = getchar(); x *= f;
}
int s[N];
struct Info {int x, y, z;};
Info operator + (Info a, Info b) {return (Info) {a.x + b.x, a.y + b.y, a.z + b.z};}
struct SegmentTree {
    struct Node {
        int l, r, s1, s2, s3, del;
    } t[N * 4];
    void build(int k, int l, int r) {
        t[k] = (Node) {l, r, 0, 0, 0, 0};
        if (l == r) return; int mid = (l + r) >> 1;
        build(k << 1, l, mid); build(k << 1 | 1, mid + 1, r);
    }
    void Add(int k, int v) {
        int l = t[k].l, r = t[k].r;
        t[k].s1 += (r - l + 1) * v;
        t[k].s2 += (l + r) * (r - l + 1) / 2 * v;
        t[k].s3 += (s[r] - s[l - 1]) * v;
        t[k].del += v;
    }
    void update(int k) {
        t[k].s1 = t[k << 1].s1 + t[k << 1 | 1].s1;
        t[k].s2 = t[k << 1].s2 + t[k << 1 | 1].s2;
        t[k].s3 = t[k << 1].s3 + t[k << 1 | 1].s3;
    }
    void pushdown(int k) {
        int x = t[k].del; t[k].del = 0;
        Add(k << 1, x), Add(k << 1 | 1, x);
    }
    void modify(int k, int L, int R, int v) {
        int l = t[k].l, r = t[k].r;
        if (L <= l && r <= R) {Add(k, v); return;}
        if (t[k].del) pushdown(k);
        int mid = (l + r) >> 1;
        if (L <= mid && mid < R)
            modify(k << 1, L, mid, v), modify(k << 1 | 1, mid + 1, R, v);
        if (R <= mid) modify(k << 1, L, R, v);
        if (L > mid) modify(k << 1 | 1, L, R, v);
        update(k);
    }
    Info query(int k, int L, int R) {
        int l = t[k].l, r = t[k].r;
        if (L <= l && r <= R) return (Info) {t[k].s1, t[k].s2, t[k].s3};
        if (t[k].del) pushdown(k); int mid = (l + r) >> 1;
        if (R <= mid) return query(k << 1, L, R);
        if (L > mid) return query(k << 1 | 1, L, R);
        return query(k << 1, L, mid) + query(k << 1 | 1, mid + 1, R);
    }
} T;
int gcd(int x, int y) {
    if (y == 0) return x;
    return gcd(y, x % y);
}
main() {
    int n, m; read(n), read(m); T.build(1, 1, n - 1);
    for (int i = 1; i <= n; i++) s[i] = s[i - 1] + i * i;
    while (m--) {
        char c = getchar();
        while (!isalpha(c)) c = getchar();
        if (c == ‘C‘) {
            int l, r, v; read(l), read(r), read(v);
            T.modify(1, l, r - 1, v);
        } else {
            int l, r; read(l), read(r);
            Info tmp = T.query(1, l, r - 1);
            int x = -(l - 1) * r * tmp.x + (l + r - 1) * tmp.y - tmp.z, y = (r - l + 1) * (r - l) / 2;
            int t = gcd(x, y); cout << x / t << ‘/‘ << y / t << "
";
        }
    }
    return 0;
}

以上是关于bzoj 2752 [HAOI2012]高速公路(road) 线段树的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2752:[HAOI2012]高速公路(road)(线段树)

BZOJ2752[HAOI2012]高速公路(road) 线段树

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

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

●BZOJ 2752 [HAOI2012]高速公路(road)

BZOJ 2752 [HAOI2012]高速公路(road) | 线段树 期望