BZOJ 3307
阿新 • • 發佈:2018-10-10
lse nod printf insert edge del 線段 tmp cpp
一棵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; }
BZOJ 3307