diff --git a/Luogu/P4556/P4556.cpp b/Luogu/P4556/P4556.cpp new file mode 100644 index 00000000..e50e4765 --- /dev/null +++ b/Luogu/P4556/P4556.cpp @@ -0,0 +1,228 @@ +#include +#include +#include +#include + +using std::cin; +using std::cout; +const char endl = '\n'; + +const int N = 1e5 + 5; + +class SegmentTree { + private: + int L, R; + + static bool cmp(std::pair a, std::pair b) { + return a.first == b.first ? a.second > b.second : a.first < b.first; + } + + struct node { + std::pair o; + node *lchild, *rchild; + + node() + : o(0, 0), lchild(nullptr), rchild(nullptr) {} + + void pushup() { + o = {0, 0}; + + if (lchild) o = std::max(o, lchild->o, cmp); + if (rchild) o = std::max(o, rchild->o, cmp); + } + }; + + node *root; + + void modify(node *&cur, int l, int r, int pos, int val) { + if (!cur) cur = new node(); + + if (l == r) { + cur->o.first += val; + cur->o.second = l; + + return; + } + + int mid = l + r >> 1; + + if (pos <= mid) modify(cur->lchild, l, mid, pos, val); + else modify(cur->rchild, mid + 1, r, pos, val); + + cur->pushup(); + } + + std::pair query(node *cur, int l, int r, int ql, int qr) { + if (!cur) return {0, 0}; + if (ql <= l && r <= qr) return cur->o; + + int mid = l + r >> 1; + std::pair res; + + if (ql <= mid) res = std::max(res, query(cur->lchild, l, mid, ql, qr), cmp); + if (qr > mid) res = std::max(res, query(cur->rchild, mid + 1, r, ql, qr), cmp); + + return res; + } + + node *merge(node *&cur_a, node *&cur_b, int l, int r) { + if (!cur_a) return cur_b; + if (!cur_b) return cur_a; + + node *cur = new node(); + + if (l == r) { + cur->o.first = cur_a->o.first + cur_b->o.first; + cur->o.second = l; + + delete cur_a; + delete cur_b; + cur_a = cur_b = nullptr; + + return cur; + } + + int mid = l + r >> 1; + + cur->lchild = merge(cur_a->lchild, cur_b->lchild, l, mid); + cur->rchild = merge(cur_a->rchild, cur_b->rchild, mid + 1, r); + + delete cur_a; + delete cur_b; + cur_a = cur_b = nullptr; + + cur->pushup(); + + return cur; + } + + void _delete(node *&cur) { + if (cur->lchild) _delete(cur->lchild); + if (cur->rchild) _delete(cur->rchild); + delete cur; + } + + public: + SegmentTree(const int &_L = 0, const int _R = 0) + : L(_L), R(_R), root(nullptr) {} + + ~SegmentTree() { + // if (root) _delete(root); + } + + void modify(int pos, int val) { + modify(root, L, R, pos, val); + } + + std::pair query(int ql, int qr) { + return query(root, L, R, ql, qr); + } + + void merge(SegmentTree &b) { + assert(L == b.L && R == b.R); + + root = merge(root, b.root, L, R); + } +}; + +int n, m, x[N], y[N], z[N], max, ans[N]; +int fa[N], dep[N], siz[N], son[N], top[N]; +std::vector g[N]; + +void dfs1(int u, int f) { + dep[u] = dep[f] + 1; + siz[u] = 1; + fa[u] = f; + + for (int v : g[u]) { + if (v == f) continue; + + dfs1(v, u); + + siz[u] += siz[v]; + + if (siz[son[u]] < siz[v]) son[u] = v; + } +} + +void dfs2(int u, int t) { + top[u] = t; + + if (!son[u]) return; + + dfs2(son[u], t); + + for (int v : g[u]) { + if (v == fa[u]) continue; + if (v == son[u]) continue; + + dfs2(v, v); + } +} + +int lca(int u, int v) { + while (top[u] != top[v]) { + if (dep[top[u]] < dep[top[v]]) std::swap(u, v); + u = fa[top[u]]; + } + + return dep[u] < dep[v] ? u : v; +} + +int main() { + std::ios::sync_with_stdio(false); + cin.tie(nullptr); + + cin >> n >> m; + + for (int i = 1, u, v; i < n; i++) { + cin >> u >> v; + + g[u].emplace_back(v); + g[v].emplace_back(u); + } + + dfs1(1, 0); + dfs2(1, 1); + + for (int i = 1; i <= m; i++) { + cin >> x[i] >> y[i] >> z[i]; + + max = std::max(max, z[i]); + } + + std::vector tr(n + 1, SegmentTree(1, max)); + + for (int i = 1; i <= m; i++) { + int p = lca(x[i], y[i]); + + tr[x[i]].modify(z[i], 1); + tr[y[i]].modify(z[i], 1); + tr[p].modify(z[i], -1); + if (fa[p]) tr[fa[p]].modify(z[i], -1); + } + + std::function dfs = [&](int u) { + for (int v : g[u]) { + if (v == fa[u]) continue; + + if (dep[v] > dep[u]) { + dfs(v); + + tr[u].merge(tr[v]); + } + } + + auto res = tr[u].query(1, max); + + if (res.second) ans[u] = res.second; + }; + + dfs(1); + + for (int i = 1; i <= n; i++) { + cout << ans[i] << endl; + } + + return 0; +}