• [HNOI2015]开店 树链剖分,主席树


    [HNOI2015]开店

    LG传送门

    蒟蒻表示不会动态淀粉质。

    先把点按年龄排序, 设(dis[i])表示(i)到根的距离。

    把我们要算的东西稍微变下形:(ans)

    [= sum limits _{i = l} ^r (dis[i] + dis[u] - 2 * dis[lca(i, u)] ]

    [= sum limits _{i = l} ^r dis[i] + (r - l + 1) * dis[u] - 2 * sum limits _{i = l} ^r dis[lca(i, u)] ]

    前面两项都很容易算,主要是最后一项不太好弄,假设我们能快速求出(sum limits _{i = 1} ^n dis[lca(i, u)]),那么我们就可以套上一个主席树解决这个问题,考虑树剖,对于每个点将这个点到根路径上的点权值加一,维护每个点的权值乘以其父边的权值的区间和,查询的时候就算一下询问点到根的路径上线段树所维护的信息和就行了。

    主席树需要标记永久化。

    //written by newbiechd
    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <algorithm>
    #define R register
    #define I inline
    #define B 1000000
    #define L long long
    using namespace std;
    const int N = 150003;
    char buf[B], *p1, *p2;
    I char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, B, stdin), p1 == p2) ? EOF : *p1++; }
    I int rd() {
        R int f = 0;
        R char c = gc();
        while (c < 48 || c > 57)
            c = gc();
        while (c > 47 && c < 58)
            f = f * 10 + (c ^ 48), c = gc();
        return f;
    }
    int s[N], dep[N], fa[N], lst[N], siz[N], son[N], dfn[N], top[N], rt[N], n, tim, T, tmp;
    L dis[N], sum[N], val[N], ans;
    struct node {
        int p, d;
        node () {}
        node (int p, int d) : p(p), d(d) {}
    }a[N];
    struct segtree {
        int p, q, d;
        L s;
    }e[N << 7];
    vector <pair <int, int> > g[N];
    I int operator < (node x, node y) { return x.d ^ y.d ? x.d < y.d : x.p < y.p; }
    I void swap(int &x, int &y) { x ^= y, y ^= x, x ^= y; }
    void dfs1(int x, int f) {
        dep[x] = dep[f] + 1, dis[x] = dis[f] + lst[x], fa[x] = f, siz[x] = 1;
        for (R int i = 0, y, m = 0; i < s[x]; ++i)
            if ((y = g[x][i].first) ^ f) {
                lst[y] = g[x][i].second, dfs1(y, x), siz[x] += siz[y];
                if (siz[y] > m)
                    m = siz[y], son[x] = y;
            }
    }
    void dfs2(int x, int t) {
        dfn[x] = ++tim, val[tim] = lst[x], top[x] = t;
        if (son[x])
            dfs2(son[x], t);
        for (R int i = 0, y; i < s[x]; ++i)
            if (!dfn[y = g[x][i].first])
                dfs2(y, y);
    }
    int insert(int k, int l, int r, int x, int y) {
        R int t = ++T;
        e[t] = e[k];
        if (x == l && y == r) {
            ++e[t].d;
            return t;
        }
        e[t].s += val[y] - val[x - 1];
        R int m = (l + r) >> 1;
        if (y <= m)
            e[t].p = insert(e[k].p, l, m, x, y);
        else
            if (m < x)
                e[t].q = insert(e[k].q, m + 1, r, x, y);
            else
                e[t].p = insert(e[k].p, l, m, x, m),
                    e[t].q = insert(e[k].q, m + 1, r, m + 1, y);
        return t;
    }
    L query(int k, int l, int r, int x, int y) {
        L o = 1ll * (val[y] - val[x - 1]) * e[k].d;
        if (x == l && y == r)
            return o + e[k].s;
        R int m = (l + r) >> 1;
        if (y <= m)
            return o + query(e[k].p, l, m, x, y);
        if (m < x)
            return o + query(e[k].q, m + 1, r, x, y);
        return o + query(e[k].p, l, m, x, m) + query(e[k].q, m + 1, r, m + 1, y);
    }
    I void modify(int x) {
        while (x)
            tmp = insert(tmp, 1, n, dfn[top[x]], dfn[x]), x = fa[top[x]];
    }
    I L calc(int x, int root) {
        L o = 0;
        while (x)
            o += query(root, 1, n, dfn[top[x]], dfn[x]), x = fa[top[x]];
        return o;
    }
    int main() {
        R int Q, A, i, x, y, z;
        n = rd(), Q = rd(), A = rd();
        for (i = 1; i <= n; ++i)
            a[i]= node(i, rd());
        for (i = 1; i < n; ++i)
            x = rd(), y = rd(), z = rd(),
                g[x].push_back(make_pair(y, z)), g[y].push_back(make_pair(x, z));
        for (i = 1; i <= n; ++i)
            s[i] = g[i].size();
        dfs1(1, 0), dfs2(1, 1), sort(a + 1, a + n + 1);
        for (i = 1; i <= n; ++i)
            sum[i] = sum[i - 1] + dis[a[i].p], val[i] += val[i - 1];
        for (i = 1; i <= n; ++i)
            modify(a[i].p), rt[i] = tmp;
        for (i = 1; i <= Q; ++i) {
            x = rd(), y = (ans + rd()) % A, z = (ans + rd()) % A;
            if (y > z)
                swap(y, z);
            y = lower_bound(a + 1, a + n + 1, node(0, y)) - a,
                z = upper_bound(a + 1, a + n + 1, node(N, z)) - a - 1;
            printf("%lld
    ", ans = 1ll * (z - y + 1) * dis[x] + sum[z] - sum[y - 1]
                   - 2ll * (calc(x, rt[z]) - calc(x, rt[y - 1])));
        }
        return 0;
    }
    
    
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    scala 时间,时间格式转换
    GIS基础知识
    客户端,Scala:Spark查询Phoenix
    Phoenix的shell操作
  • 原文地址:https://www.cnblogs.com/cj-chd/p/10421261.html
Copyright © 2020-2023  润新知