BZOJ 3307
一棵n个点的树,m次操作,每次选择两个点x,y,往x到y的路径上每个点放一个z类型的物品。问最后每个点存放最多的是哪种物品。
\[n,m \leq 10^5
\]
树上差分然后线段树合并
const int MAXN = 100000 + 5, LOG = 60;
struct SegmentTree {
struct Node {
Node *ch[2];
int max, num;
#define max(x) ((x) ? (x)->max : 0)
#define num(x) ((x) ? (x)->num : 0)
void push_up() {
max = max(ch[0]);
num = num(ch[0]);
if (chkmax(max, max(ch[1])))
num = num(ch[1]);
}
} nd[MAXN * LOG], *pos;
SegmentTree() {
pos = nd;
}
Node *new_node() {
pos->max = pos->num = 0;
pos->ch[0] = pos->ch[1] = NULL;
return pos ++;
}
void insert(Node *&o, int l, int r, int p, int x) {
if (!o)
o = new_node();
if (l == r) {
o->max += x;
o->num = p;
return;
}
int mid = (l + r) >> 1;
if (p <= mid)
insert(o->ch[0], l, mid, p, x);
else
insert(o->ch[1], mid + 1, r, p, x);
o->push_up();
}
Node *merge(Node *&o, Node *&p, int l, int r) {
if (!o || !p)
return o ? o : p;
if (l == r) {
o->max += p->max;
p = NULL;
return o;
}
int mid = (l + r) >> 1;
if (o->ch[0] || p->ch[0])
o->ch[0] = merge(o->ch[0], p->ch[0], l, mid);
if (o->ch[1] || p->ch[1])
o->ch[1] = merge(o->ch[1], p->ch[1], mid + 1, r);
p = NULL;
o->push_up();
return o;
}
} Seg;
int ans[MAXN], lg[MAXN], n, m, sz;
struct Tree {
int hed[MAXN], nxt[MAXN * 2], to[MAXN * 2], fa[LOG][MAXN], dep[MAXN], cnt;
SegmentTree::Node *ptr[MAXN];
void add_edge(int u, int v) {
++ cnt;
to[cnt] = v;
nxt[cnt] = hed[u];
hed[u] = cnt;
}
void DFS1(int u) {
for (int i = 1; 1 << i <= dep[u]; ++ i)
fa[i][u] = fa[i - 1][fa[i - 1][u]];
for (int e = hed[u]; e; e = nxt[e]) {
int v = to[e];
if (v != fa[0][u]) {
fa[0][v] = u;
dep[v] = dep[u] + 1;
DFS1(v);
}
}
}
int LCA(int u, int v) {
if (dep[u] < dep[v])
std::swap(u, v);
int del = dep[u] - dep[v];
For(i, 0, lg[n])
if (del & (1 << i))
u = fa[i][u];
if (u == v)
return u;
Rep(i, lg[n], 0)
if (fa[i][u] != fa[i][v])
u = fa[i][u], v = fa[i][v];
return fa[0][u];
}
void DFS2(int u) {
for (int e = hed[u]; e; e = nxt[e]) {
int v = to[e];
if (v != fa[0][u]) {
DFS2(v);
ptr[u] = Seg.merge(ptr[u], ptr[v], 1, sz);
}
}
ans[u] = num(ptr[u]);
}
} T;
struct Query {
int u, v, z, p;
} q[MAXN];
int tmp[MAXN], to[MAXN];
int main() {
scanf("%d%d", &n, &m);
For(i, 2, n) {
int u, v;
scanf("%d%d", &u, &v);
T.add_edge(u, v);
T.add_edge(v, u);
}
lg[0] = -1;
For(i, 1, n)
lg[i] = lg[i >> 1] + 1;
T.DFS1(1);
For(i, 1, m) {
scanf("%d%d%d", &q[i].u, &q[i].v, &q[i].z);
tmp[i] = q[i].z;
}
std::sort(tmp + 1, tmp + m + 1);
sz = std::unique(tmp + 1, tmp + m + 1) - tmp;
For(i, 1, m) {
q[i].p = std::lower_bound(tmp + 1, tmp + sz, q[i].z) - tmp;
Seg.insert(T.ptr[q[i].u], 1, sz, q[i].p, 1);
Seg.insert(T.ptr[q[i].v], 1, sz, q[i].p, 1);
int lca = T.LCA(q[i].u, q[i].v);
Seg.insert(T.ptr[lca], 1, sz, q[i].p, -1);
Seg.insert(T.ptr[T.fa[0][lca]], 1, sz, q[i].p, -1);
to[q[i].p] = q[i].z;
}
T.DFS2(1);
For(i, 1, n)
printf("%d\n", to[ans[i]]);
return 0;
}