题目链接
首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献。
再把每个点与\(k\)的lca的距离差分一下,则只需要统计每个点与\(k\)的lca深度。这个东西等价于所有的链与\(k\)到根的链的并。
树剖+主席树维护一下。这题的主席树需要区间加1,可以标记永久化合并标记
复杂度\(O(n\log ^2n)\)
#include<bits/stdc++.h> #define Pair pair<LL, LL> #define MP(x, y) make_pair(x, y) #define fi first #define se second //#define int long long #define LL long long #define ull unsigned long long #define Fin(x) {freopen(#x".in","r",stdin);} #define Fout(x) {freopen(#x".out","w",stdout);} using namespace std; const int MAXN = 2e5 + 10, mod = 1e9 + 7, INF = 1e9 + 10; const double eps = 1e-9; template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;} template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;} template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;} template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);} template <typename A, typename B> inline LL mul(A x, B y) {return 1ll * x * y % mod;} template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;} template <typename A> inline void debug(A a){cout << a << '\n';} template <typename A> inline LL sqr(A x){return 1ll * x * x;} template <typename A, typename B> inline LL fp(A a, B p, int md = mod) {int b = 1;while(p) {if(p & 1) b = mul(b, a);a = mul(a, a); p >>= 1;}return b;} template <typename A> A inv(A x) {return fp(x, mod - 2);} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } LL lastans; int type, N, Q, p[MAXN], fa[MAXN], top[MAXN], dep[MAXN], son[MAXN], siz[MAXN], dfn[MAXN], rev[MAXN], times; LL Esum[MAXN], sdis[MAXN], valE[MAXN]; vector<Pair> v[MAXN]; void dfs(int x, int _fa) { fa[x] = _fa; dep[x] = dep[_fa] + 1; siz[x] = 1; for(auto &tmp : v[x]) { int to = tmp.first, w = tmp.se; if(to == _fa) continue; Esum[to] = Esum[x] + w; valE[to] = w; dfs(to, x); siz[x] += siz[to]; if(siz[to] > siz[son[x]]) son[x] = to; } } void dfs2(int x, int topf) { top[x] = topf; dfn[x] = ++times; rev[times] = x; if(!son[x]) return ; dfs2(son[x], topf); for(auto &to : v[x]) { if(top[to.fi]) continue; dfs2(to.fi, to.fi); } } int LCA(int x, int y) { while(top[x] ^ top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x, y); x = fa[top[x]]; } return dep[x] < dep[y] ? x : y; } int rt[MAXN], ls[MAXN * 80], rs[MAXN * 80], cnt; LL sumc[MAXN * 80], sum[MAXN * 80], lzy[MAXN * 80]; void Build(int &k, int l, int r) { k = ++cnt; if(l == r) {sumc[k] = valE[rev[l]]; return ;} int mid = l + r >> 1; Build(ls[k], l, mid); Build(rs[k], mid + 1, r); sumc[k] = sumc[ls[k]] + sumc[rs[k]]; } Pair operator + (const Pair a, const Pair b) { return {a.fi + b.fi, a.se + b.se}; } void Add(int &k, int l, int r, int ql, int qr) { ++cnt; int nw = cnt; ls[nw] = ls[k]; rs[nw] = rs[k]; sumc[nw] = sumc[k]; sum[nw] = sum[k]; lzy[nw] = lzy[k]; k = cnt; if(ql <= l && r <= qr) { lzy[k]++, sum[k] += sumc[k]; return ; } int mid = l + r >> 1; if(ql <= mid) Add(ls[k], l, mid, ql, qr); if(qr > mid) Add(rs[k], mid + 1, r, ql, qr); sum[k] = sum[ls[k]] + sum[rs[k]] + lzy[k] * sumc[k]; } Pair Query(int k, int l, int r, int ql, int qr) { if(ql <= l && r <= qr) return {sum[k], sumc[k]}; Pair res = {0, 0}; int mid = l + r >> 1; if(ql <= mid) res = res + Query(ls[k], l, mid, ql, qr); if(qr > mid) res = res + Query(rs[k], mid + 1, r, ql, qr); res.fi += 1ll * res.se * lzy[k]; return res; } void insert(int x) { int pre = x; rt[x] = rt[fa[x]]; x = p[x]; while(x)Add(rt[pre], 1, N, dfn[top[x]], dfn[x]), x = fa[top[x]]; } void dfs3(int x, int fa) { sdis[x] = sdis[fa] + Esum[p[x]]; insert(x); for(auto &to : v[x]) if(to.fi != fa) dfs3(to.fi, x); } LL solve(int u, int k) { if(!k) return 0; LL res = sdis[k] + 1ll * dep[k] * Esum[u]; while(u) { res -= Query(rt[k], 1, N, dfn[top[u]], dfn[u]).fi << 1; u = fa[top[u]]; } return res; } signed main() { type = read(); N = read(); Q = read(); for(int i = 1; i <= N - 1; i++) { int x = read(),y = read(), w = read(); v[x].push_back({y, w}); v[y].push_back({x, w}); } for(int i = 1; i <= N; i++) p[i] = read(); dfs(1, 0); dfs2(1, 1); Build(rt[0], 1, N); dfs3(1, 0); while(Q--) { int tu = read() ^ (lastans * type), tv = read() ^ (lastans * type), tk = read() ^ (lastans * type); lastans = solve(tk, tu) + solve(tk, tv) - solve(tk, LCA(tu, tv)) - solve(tk, fa[LCA(tu, tv)]); cout << lastans << '\n'; } return 0; }