zoukankan      html  css  js  c++  java
  • 题解 P7581 【「RdOI R2」路径权值(distance)】

    (huge exttt{P7581})

    前言

    刚学了长剖,比赛快结束的时候进来看了一眼,口胡秒了,写的时候发现巨大多细节,口胡不行

    长剖永存,空间卡的好啊!

    题意

    不做赘述。

    思路

    首先看到这是一道和深度有极大的关系,自然联想到建几个以深度为下标的数组通过 DFS 遍历并动态修改解决问题,而且可以用启发式合并的类似思路合并子树信息,因此能联想到用长链剖分解决问题。

    但是长链剖分对数组空间和对子树信息继承关系要求比较苛刻,比如一开始我是这么想的:

    • 记录 (val[u][i]) 表示以 (u) 为根的子树所有深度为 (i) 的节点到 (u) 的路径长度之和。
    • 记录 (dis[u][i]) 表示以 (u) 为根的子树所有深度为 (i) 的节点之间的距离之和。
    • 记录 (siz[u][i]) 表示以 (u) 为根的子树所有深度为 (i) 的节点的个数。

    (dis[u])(siz[u]) 的转移都很好写:

    [dis[u][i]=sum_{vin son(u)}dis[v][i-1]+(siz[u][i]-siz[v][i-1])*(val[v][i-1]+siz[v][i-1]*w(u,v)) ]

    (上面的公式在代码中为了方便并不是如此一模一样实现)

    [siz[u][i]=[i==0]+sum_{vin son(n)}siz[v][i-1] ]

    但是对于 (val[u]) 的转移就出了问题,因为 (val[u]) 的值和 (u) 这个点有关,也就是说从重儿子转移过来的还要加上一个值(还和 (siz[maxson(u)][i]) 有关),不能直接继承,而暴力再枚举一遍重儿子的深度再加显然复杂度错误。

    以下与出题人思路不同。

    但是还是可以优化的,我们可以再建一个 (tag[u]) 数组,即懒标记优化,每次 (u) 节点合并前,因为先继承了重儿子的 (val[u]) 数组,我们需要在 (tag[u][1]) 加上一个 (w(u,maxson(u))),当要访问 (val[u][i]) 的时候,我们要先访问懒标记,更新并下传,因为下穿懒标记在更新 (val[u][i])(siz[u][i]) 前,所以不会访问到 (dis[u][i]),所以加值延迟不会影响最终大小。

    代码

    感觉这样口胡还是有点难懂QwQ。

    目前除出题人外的最优解,(rk1是数据改之前交的)。

    int a, b, mx[N + 5],
        son[N + 5][2];
    LL op[N * 8 + 5], *tag[N + 5], ans[N + 5], *dis[N + 5], *val[N + 5], *tmp = op, *siz[N + 5];
    vector<pii> st[N + 5], ask[N + 5];
    
    void ins(int n, int len) {
        val[n] = tmp;
        tmp += len + 1;
        dis[n] = tmp;
        tmp += len + 1;
        siz[n] = tmp;
        tmp += len + 1;
        tag[n] = tmp;
        tmp += len + 1;
    }
    void add(int n, int i) {
        (tag[n][i + 1] += tag[n][i]) %= mod;
        (val[n][i] += tag[n][i] * siz[n][i] % mod) %= mod;
        tag[n][i] = 0;
    }
    void dfs(int n, int fa) {
        mx[n] = 1;
        rep(i, 0, siz(st[n]) - 1) {
            int v = st[n][i].fi;
            if (v == fa) continue;
            dfs(v, n);
            if (mx[v] > mx[son[n][0]]) son[n][0] = v, son[n][1] = st[n][i].se;
        }
        mx[n] = mx[son[n][0]] + 1;
    }
    void Dfs(int n, int fa) {
        if (son[n][0]) {
            val[son[n][0]] = val[n] + 1;
            dis[son[n][0]] = dis[n] + 1;
            siz[son[n][0]] = siz[n] + 1;
            tag[son[n][0]] = tag[n] + 1;
            Dfs(son[n][0], n);
        }
        siz[n][0] = 1;
        tag[n][1] = son[n][1];
        rep(i, 0, siz(st[n]) - 1) {
            int v = st[n][i].fi, p = st[n][i].se;
            if (v == fa || v == son[n][0]) continue;
            ins(v, mx[v]);
            Dfs(v, n);
            rep(j, 1, mx[v]) {
                if (j != mx[v]) add(v, j);
                add(n, j);
                (dis[n][j] += val[n][j] * siz[v][j - 1] % mod +
                              (val[v][j - 1] + p * siz[v][j - 1] % mod) *
                              siz[n][j] % mod + dis[v][j - 1]) %= mod;
                (val[n][j] += val[v][j - 1] + p * siz[v][j - 1] % mod) %= mod;
                (siz[n][j] += siz[v][j - 1]) %= mod;
            }
        }
        rep(i, 0, siz(ask[n]) - 1) {
            int x = ask[n][i].fi;
            ans[ask[n][i].se] = dis[n][x];
        }
    }
    
    signed main() {
        // freopen("in1.in", "r", stdin);
        // freopen("out.out", "w", stdout);
        a = read();
        b = read();
        int x, y, z;
        rep(i, 1, a - 1) {
            x = read();
            y = read();
            z = read();
            st[x].PB(MP(y, z));
            st[y].PB(MP(x, z));
        }
        dfs(1, 0);
        rep(i, 1, b) {
            x = read();
            y = read();
            if (y <= mx[x] - 1)
                ask[x].PB(MP(y, i));
        }
        ins(1, mx[1]);
        Dfs(1, 0);
        rep(i, 1, b) printf("%lld
    ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    在SQLite中使用索引优化查询速度
    SQLite支持的SQL数据操作
    left (outer) join , right (outer) join, full (outer) join, (inner) join, cross join 区别
    深入理解Android内存管理原理(六)
    Merge Sorted Array
    Sort Colors
    Construct Binary Tree from Preorder and Inorder Traversal
    Binary Tree Postorder Traversal
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/RedreamMer/p/14732487.html
Copyright © 2011-2022 走看看