题目大意
给你一棵(n)个点的树,有(m)个操作,每次操作将(x)到(y)的路径上的每个点都放入一个颜色为(z)的球。你需要求出最后每个点里个数最多的球是哪种颜色的。
分析
通过树链剖分把树上路径转化为若干区间,把树上问题转化为区间问题,然后结合差分思想,在左端点加上(+z)标记,在右端点(+1)的位置加上(-z)标记,我们从左往右做,用线段树维护当前出现次数最多的颜色,时间复杂度(O(nlog^2n))。最好将颜色离散化,这样线段树就不必动态开点了。
Code
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
const int N = 100007;
int n, m, len, x[N], y[N], z[N], arr[N], ans[N];
int tot, cnt, st[N], to[N << 1], nx[N << 1], son[N], top[N], dfn[N], fa[N], size[N], ord[N], dep[N];
void add(int u, int v) { to[++tot] = v, nx[tot] = st[u], st[u] = tot; }
vector<int> lis[N];
void dfs(int u)
{
size[u] = 1;
for (int i = st[u]; i; i = nx[i])
if (to[i] != fa[u])
{
dep[to[i]] = dep[u] + 1, fa[to[i]] = u, dfs(to[i]), size[u] += size[to[i]];
if (size[to[i]] > size[son[u]]) son[u] = to[i];
}
}
void dfs2(int u, int tp)
{
dfn[u] = ++cnt, ord[cnt] = u, top[u] = tp;
if (son[u]) dfs2(son[u], tp);
for (int i = st[u]; i; i = nx[i]) if (to[i] != fa[u] && to[i] != son[u]) dfs2(to[i], to[i]);
}
struct note { int id, cnt; } tr[N * 4];
note max(note a, note b)
{
if (a.cnt == b.cnt) return a.id < b.id ? a : b;
return a.cnt > b.cnt ? a : b;
}
void build(int rt, int l, int r)
{
if (l == r) { tr[rt] = (note){l, 0}; return; }
int mid = l + r >> 1;
build(lson, l, mid), build(rson, mid + 1, r);
}
void ins(int rt, int l, int r, int po, int v)
{
if (l == r) { tr[rt].cnt += v; return; }
int mid = l + r >> 1;
if (po <= mid) ins(lson, l, mid, po, v);
else ins(rson, mid + 1, r, po, v);
tr[rt] = max(tr[lson], tr[rson]);
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1, u, v; i < n; i++) scanf("%d%d", &u, &v), add(u, v), add(v, u);
dep[1] = 1, dfs(1), dfs2(1, 1);
for (int i = 1; i <= m; i++) scanf("%d%d%d", &x[i], &y[i], &z[i]), arr[++len] = z[i];
sort(arr + 1, arr + len + 1);
len = unique(arr + 1, arr + len + 1) - arr - 1;
for (int i = 1, u, v, w; i <= m; i++)
{
u = x[i], v = y[i], w = lower_bound(arr + 1, arr + len + 1, z[i]) - arr;
while (top[u] != top[v])
{
if (dep[top[u]] < dep[top[v]]) swap(u, v);
lis[dfn[top[u]]].push_back(w), lis[dfn[u] + 1].push_back(-w);
u = fa[top[u]];
}
if (dep[u] < dep[v]) swap(u, v);
lis[dfn[v]].push_back(w), lis[dfn[u] + 1].push_back(-w);
}
build(1, 1, len);
for (int i = 1; i <= n; i++)
{
int sz = lis[i].size();
for (int j = 0, k; j < sz; j++)
{
k = lis[i][j];
if (k > 0) ins(1, 1, len, k, 1);
else ins(1, 1, len, -k, -1);
}
ans[ord[i]] = arr[tr[1].cnt ? tr[1].id : 0];
}
for (int i = 1; i <= n; i++) printf("%d
", ans[i]);
return 0;
}