題目連接php
題意:c++
分糧食我就當成塗色了。有n個點的一棵樹,在a到b的路上都塗上c顏色,顏色可重複疊加,問最後每個點的最大顏色數量的顏色類型。ui
思路:blog
首先這題的輸出是每個點最後的狀況,考慮離線作法。簡化版問題:在一條線段上塗色,問每一個點的最後的狀況,假設在[a, b]區間塗色,那麼在開始的位置a標記開始塗色,在結束的位置標記結束塗色,一棵動態的顏色樹,維護當前顏色數量最大的數量。那麼這題也能夠考慮這麼作,先對樹進行樹鏈剖分,而後按照剖分順序dfn來遍歷,提早讀入全部操做,在塗色的兩端標記,後面操做和簡化版同樣了。get
#include <bits/stdc++.h> const int N = 1e5 + 5; std::vector<int> edges[N]; int n, m; //顏色樹 #define lson l, mid, o << 1 #define rson mid + 1, r, o << 1 | 1 int mx[N<<2]; void push_up(int o) { mx[o] = std::max (mx[o<<1], mx[o<<1|1]); } void build(int l, int r, int o) { mx[o] = 0; if (l == r) return ; int mid = l + r >> 1; build (lson); build (rson); } void updata(int p, int c, int l, int r, int o) { if (l == r) { mx[o] += c; return ; } int mid = l + r >> 1; if (p <= mid) updata (p, c, lson); else updata (p, c, rson); push_up (o); } int query(int l, int r, int o) { if (l == r) return l; int mid = l + r >> 1; if (mx[o<<1] == mx[o]) return query (lson); else return query (rson); } int sz[N], fa[N], dfn[N], belong[N]; int idx[N]; int tim; void DFS2(int u, int chain) { dfn[u] = ++tim; idx[tim] = u; belong[u] = chain; int k = 0; for (auto v: edges[u]) { if (v == fa[u]) continue; if (sz[v] > sz[k]) k = v; } if (k) DFS2 (k, chain); for (auto v: edges[u]) { if (v == fa[u] || v == k) continue; DFS2 (v, v); } } void DFS(int u, int pa) { sz[u] = 1; fa[u] = pa; for (auto v: edges[u]) { if (v == pa) continue; DFS (v, u); sz[u] += sz[v]; } } std::vector<int> add[N], sub[N]; int ans[N]; void mark(int a, int b, int c) { int p = belong[a], q = belong[b]; while (p != q) { if (dfn[p] < dfn[q]) { std::swap (p, q); std::swap (a, b); } add[dfn[p]].push_back (c); sub[dfn[a]+1].push_back (c); //son[a] a = fa[p]; p = belong[a]; } if (dfn[a] < dfn[b]) std::swap (a, b); add[dfn[b]].push_back (c); sub[dfn[a]+1].push_back (c); } void prepare() { sz[0] = 0; DFS (1, 0); tim = 0; DFS2 (1, 1); } int main() { while (scanf ("%d%d", &n, &m) == 2 && n + m) { for (int i=1; i<=n; ++i) { edges[i].clear (); add[i].clear (); sub[i].clear (); } for (int i=1; i<n; ++i) { int u, v; scanf ("%d%d", &u, &v); edges[u].push_back (v); edges[v].push_back (u); } prepare (); int maxc = 1; for (int i=1; i<=m; ++i) { int a, b, c; scanf ("%d%d%d", &a, &b, &c); mark (a, b, c); maxc = std::max (maxc, c); } build (1, maxc, 1); //dfn for (int i=1; i<=n; ++i) { for (int j=0; j<add[i].size (); ++j) { updata (add[i][j], 1, 1, maxc, 1); } for (int j=0; j<sub[i].size (); ++j) { updata (sub[i][j], -1, 1, maxc, 1); } ans[idx[i]] = mx[1] ? query (1, maxc, 1) : 0; } for (int i=1; i<=n; ++i) { printf ("%d\n", ans[i]); } } return 0; }