Featured image of post 2700

2700

Birthday

出处:CF494D

题目大意:

数据范围:

思路:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
const ll MOD = 1e9 + 7;
ll norm(ll x) {
    x %= MOD;
    if (x < 0) x += MOD;
    return x;
}
class TreeAncestor {
    vector<int> depth;       // 深度
    vector<vector<int>> pa;  // 2^i祖先

public:
    TreeAncestor(vector<vector<int>>& edges) {  // 直接传边数组
        int n = edges.size() + 1;
        int m = bit_width(unsigned(n));
        vector<vector<int>> ma(n);  // 这里还是0-based
        for (auto& p : edges) {
            int x = p[0], y = p[1];
            ma[x].push_back(y);
            ma[y].push_back(x);
        }
        depth.resize(n);
        pa.resize(n, vector<int>(m, -1));
        auto dfs = [&](auto&& self, int x, int fa) -> void {
            pa[x][0] = fa;
            for (int y : ma[x]) {
                if (y == fa) continue;
                depth[y] = depth[x] + 1;
                self(self, y, x);
            }
            return;
        };  // 预处理深度
        dfs(dfs, 0, -1);
        for (int i = 0; i < m - 1; i++) {
            for (int x = 0; x < n; x++) {
                if (pa[x][i] == -1) continue;
                pa[x][i + 1] = pa[pa[x][i]][i];
            }
        }  // 预处理2^i祖先
    }

    int get_depth(int x) { return depth[x]; }  // 获取某个点的深度

    int get_kth_ancestor(int node, int k) {
        for (int x = k; node != -1 && x > 0; x -= lowbit(x)) {
            node = pa[node][countr_zero((unsigned)x)];
        }
        return node;
    }  // 得到第k个祖先,类似树状数组的倍增

    int get_lca(int x, int y) {
        if (depth[x] > depth[y]) swap(x, y);
        y = get_kth_ancestor(y, depth[y] - depth[x]);  // 先跳到深度相同
        if (x == y) return x;
        for (int i = pa[x].size() - 1; i >= 0; i--) {
            int px = pa[x][i], py = pa[y][i];
            if (px != py) {
                x = px, y = py;
            }  // 倍增跳
        }
        return pa[x][0];
    }  // 得到最近公共祖先
};
void solve() {
    int n, x, y, z, q;
    cin >> n;
    vi a(n, -1);
    vector<vector<pii>> ma(n);
    vvi edges;
    rep(i, 1, n - 1) {
        cin >> x >> y >> z;
        ma[x - 1].emplace_back(y - 1, z);
        ma[y - 1].emplace_back(x - 1, z);
        edges.push_back({x - 1, y - 1});
    }
    TreeAncestor ta(edges);
    vl siz(n);
    vl dis(n);
    vl down1(n);
    vl down2(n);
    vl all1(n);
    vl all2(n);
    auto calc = [&](int x, int y) -> ll { return norm(dis[x] + dis[y] - 2LL * dis[ta.get_lca(x, y)]); };
    auto is_ancestor = [&](int x, int y) -> bool { return ta.get_lca(x, y) == x; };
    auto dfs = [&](this auto&& dfs, int x, int pa) -> void {
        siz[x] = 1, down1[x] = 0, down2[x] = 0;
        for (auto& [y, z] : ma[x]) {
            if (y == pa) continue;
            dis[y] = norm(dis[x] + z);
            dfs(y, x);
            siz[x] += siz[y];
            down1[x] = norm(down1[x] + down1[y] + siz[y] * z % MOD);
            down2[x] = norm(down2[x] + down2[y] + 2LL * z * down1[y] + siz[y] * z % MOD * z % MOD);
        }
    };
    dfs(0, -1);
    all1[0] = down1[0], all2[0] = down2[0];
    auto dfs2 = [&](this auto&& dfs2, int x, int pa) -> void {
        for (auto& [y, z] : ma[x]) {
            if (y == pa) continue;
            ll tem = norm(down1[y] + siz[y] * z % MOD);
            all1[y] = norm(all1[x] + norm(n - 2LL * siz[y]) * z % MOD);
            all2[y] = norm(all2[x] + 2LL * z % MOD * all1[x] % MOD - 4LL * z % MOD * tem % MOD + 1LL * n * z % MOD * z % MOD);
            dfs2(y, x);
        }
        return;
    };
    dfs2(0, -1);
    cin >> q;
    rep(i, 0, q - 1) {
        cin >> x >> y;
        x--, y--;
        ll tem = calc(x, y);
        ll ans = 0;
        if (is_ancestor(y, x)) {
            ans = norm(all2[x] - 2LL * ((n - siz[y]) * tem % MOD * tem % MOD + 2LL * tem % MOD * norm(all1[y] - down1[y]) +
                                        norm(all2[y] - down2[y])));
        } else {
            ans = norm(2LL * norm(siz[y] * tem % MOD * tem % MOD + 2LL * tem % MOD * down1[y] % MOD + down2[y]) - all2[x]);
        }
        cout << ans << endl;
    }
    return;
}