loj2553. «CTSC2018» писал зависание насилия

Смысл проблем

Учитывая два дерева \ (T, T '\) , ищет
\ [\ макс _ {(х , у)} dep_x + dep_y - (dep_ {LCA (х, у)} + отд' _ {LCA «(х, у)}) \]

решение проблемы

Через некоторое упрощение, становится требование
\ [\ макс _ {(х , у)} \ гидроразрыва {1} {2} dep_x + \ гидроразрыва {1} {2} dep_y + \ гидроразрыва {1} {2} дис (х, у) - отд '
_ {LCA' (х, у)} \] существует два основных подхода.
Одним из них является виртуальной точки края + дерево + дп.
Это не материализовались.
Другая сторона расставание + пунктирная дерево слияния.
Рассмотрим первый суб-дерево для стороны, при условии \ (D_X \) из \ (Х \) в сторону текущего расстояния к югу от центра, искание
\ [\ макс _ {(х , у)} \ гидроразрыва {1} {2 } (dep_x + D_X) + \
гидроразрыва {1} {2} (dep_y + D_X) - DEP '_ {LCA' (х, у)} \] в частичной стороны, передняя половина части легко получается.
Рассмотрим фиксированную заднюю часть, то есть, перечисление \ (X, Y \) LCA во втором дереве.
LCA перечислены, чтобы гарантировать , что \ (х, у \) в суб-дерево LCA, как это сделать?
Рассмотрим класс деревьев , чтобы построить динамическое дерево рецепта сегмента по отношению к каждой точке второго дерева, каждый из которых поддерживает это дерево в дереве после первой точки максимального вклада (т.е. точка деления цельного зерна на стороне дендрограммы стали два суб-деревья, чтобы записать максимальный вклад в двух точках к югу от дерева сгенерированных (были записаны), в виде вклада \ (dep_x + D_X \)), Снизу вверх , а затем будут объединены на втором дереве. Время слияния или объединения левого и левого, правого и право слияния, слева и справа может генерировать только вклады, направо и налево могут генерировать только вклады, и это похоже на слияние линии дерева. Что же касается сложности, вероятно , в зависимости от природы (бинарное дерево) верхней части структуры суб-дерева, хорошо это.
Возможно \ (\ mathcal O (п \ лог п) \) есть.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 750005;
struct tr {
    int tot, lnk[N], nxt[N << 1], son[N << 1], w[N << 1];
    tr () {
        tot = 1;
        memset(lnk, 0, sizeof lnk);
        memset(nxt, 0, sizeof nxt);
    }
    void add (int x, int y, int z) {
        nxt[++tot] = lnk[x], lnk[x] = tot, son[tot] = y, w[tot] = z;
    }
    void adds (int x, int y, int z) {
        add(x, y, z), add(y, x, z);
    }
} T0, T1, T2;

int n, m, s, e, mn, tot; ll ans;
int sz[N], *pos[N], rt[N], las[N], lc[N * 20], rc[N * 20];
ll dep[N], mx[N * 20][2];
bool ban[N << 1];
void append (int x, int y, int z) {
    T1.adds(las[x], ++m, 0), las[x] = m;
    T1.adds(m, y, z);
}
void build (int x, int p, ll d) {
    dep[x] = d;
    for (int j = T0.lnk[x]; j; j = T0.nxt[j]) {
        if (T0.son[j] != p) {
            append(x, T0.son[j], T0.w[j]);
            build(T0.son[j], x, d + T0.w[j]);
        }
    }
}
void gete (int x, int p) {
    sz[x] = 1;
    for (int j = T1.lnk[x], v; j; j = T1.nxt[j]) {
        if (!ban[j >> 1] && T1.son[j] != p) {
            gete(T1.son[j], x);
            sz[x] += sz[T1.son[j]];
            v = max(sz[T1.son[j]], s - sz[T1.son[j]]);
            if (mn > v) {
                e = j, mn = v;
            }
        }
    }
}
void dfs (int x, int p, ll d, bool f) {
    if (x <= n) {
        *pos[x] = ++tot;
        mx[tot][f] = d + dep[x];
        mx[tot][f ^ 1] = -1e18;
        pos[x] = (f ? &rc[tot] : &lc[tot]);
    }
    for (int j = T1.lnk[x]; j; j = T1.nxt[j]) {
        if (!ban[j >> 1] && T1.son[j] != p) {
           dfs(T1.son[j], x, d + T1.w[j], f);
        }
    }
}
void dac (int x, int curs) {
    if (curs > 1) {
        s = curs, e = -1, mn = 1e9;
        gete(x, 0);
        ban[e >> 1] = 1;
        int u = T1.son[e ^ 1], v = T1.son[e], su = s - sz[v], sv = sz[v];
        dfs(u, 0, 0, 0), dfs(v, 0, T1.w[e], 1);
        dac(u, su), dac(v, sv);
    }
}
int merge (int x, int y, ll d) {
    if (!x || !y) {
        return x | y;
    }
    ans = max(ans, (mx[x][0] + mx[y][1]) / 2 - d);
    ans = max(ans, (mx[y][0] + mx[x][1]) / 2 - d);
    mx[x][0] = max(mx[x][0], mx[y][0]);
    mx[x][1] = max(mx[x][1], mx[y][1]);
    lc[x] = merge(lc[x], lc[y], d);
    rc[x] = merge(rc[x], rc[y], d);
    return x;
}
void solve (int x, int p, ll d) {
    ans = max(ans, dep[x] - d);
    for (int j = T2.lnk[x]; j; j = T2.nxt[j]) {
        if (T2.son[j] != p) {
            solve(T2.son[j], x, d + T2.w[j]);
            rt[x] = merge(rt[x], rt[T2.son[j]], d);
        }
    }
}
int main () {
    scanf("%d", &n);
    for (int i = 1, x, y, z; i < n; ++i) {
        scanf("%d%d%d", &x, &y, &z);
        T0.adds(x, y, z);
    }
    for (int i = 1; i <= n; ++i) {
        las[i] = i, pos[i] = &rt[i];
    }
    m = n;
    build(1, 0, 0);
    dac(1, m);
    for (int i = 1, x, y, z; i < n; ++i) {
        scanf("%d%d%d", &x, &y, &z);
        T2.adds(x, y, z);
    }
    solve(1, 0, 0);
    printf("%lld\n", ans);
    return 0;
}

рекомендация

отwww.cnblogs.com/psimonw/p/11480989.html