BZOJ 3307: 雨天的尾巴
用权值线段树维护最大值和其位置,树上差分作标记
再在树上线段树合并
这里有两个结论
- 树上差分后,子树中每个孩子的值之和就是当前节点的值
- 如果刚开始只有一个叶子节点的线段树有n个,那么合并成一棵线段树的复杂度为$O(nlogn)$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n, q; 6 int x[N], y[N], z[N]; 7 struct Graph 8 { 9 struct node 10 { 11 int to, nx; 12 node() {} 13 node(int to, int nx) : to(to), nx(nx) {} 14 }a[N << 2]; 15 int head[N], pos; 16 void add(int u, int v) 17 { 18 a[++pos] = node(v, head[u]); head[u] = pos; 19 a[++pos] = node(u, head[v]); head[v] = pos; 20 } 21 }G; 22 #define erp(u) for (int it = G.head[u], v = G.a[it].to; it; it = G.a[it].nx, v = G.a[it].to) 23 24 int b[N]; 25 void Hash() 26 { 27 b[0] = 0; 28 for (int i = 1; i <= q; ++i) b[++b[0]] = z[i]; 29 sort(b + 1, b + 1 + b[0]); 30 b[0] = unique(b + 1, b + 1 + b[0]) - b - 1; 31 for (int i = 1; i <= q; ++i) z[i] = lower_bound(b + 1, b + 1 + b[0], z[i]) - b; 32 } 33 34 int fa[N], deep[N], sze[N], son[N], top[N]; 35 void DFS(int u) 36 { 37 sze[u] = 1; 38 erp(u) if (v != fa[u]) 39 { 40 fa[v] = u; 41 deep[v] = deep[u] + 1; 42 DFS(v); 43 sze[u] += sze[v]; 44 if (!son[u] || sze[v] > sze[son[u]]) son[u] = v; 45 } 46 } 47 48 void getpos(int u, int sp) 49 { 50 top[u] = sp; 51 if (!son[u]) return; 52 getpos(son[u], sp); 53 erp(u) if (v != fa[u] && v != son[u]) 54 getpos(v, v); 55 } 56 57 int lca(int u, int v) 58 { 59 while (top[u] != top[v]) 60 { 61 if (deep[top[u]] < deep[top[v]]) swap(u, v); 62 u = fa[top[u]]; 63 } 64 return deep[u] > deep[v] ? v : u; 65 } 66 67 namespace SEG 68 { 69 #define M N * 70 70 int T[N], lt[M], rt[M], Max[M], pos[M], cnt; 71 void pushup(int now) 72 { 73 int ls = lt[now], rs = rt[now]; 74 if (Max[ls] >= Max[rs]) 75 { 76 Max[now] = Max[ls]; 77 pos[now] = pos[ls]; 78 } 79 else 80 { 81 Max[now] = Max[rs]; 82 pos[now] = pos[rs]; 83 } 84 } 85 void update(int &now, int l, int r, int loc, int v) 86 { 87 if (!now) now = ++cnt; 88 if (l == r) 89 { 90 Max[now] += v; 91 pos[now] = l; 92 return; 93 } 94 int mid = (l + r) >> 1; 95 if (loc <= mid) update(lt[now], l, mid, loc, v); 96 else update(rt[now], mid + 1, r, loc, v); 97 pushup(now); 98 } 99 int merge(int now, int pre, int l, int r) 100 { 101 if (!now | !pre) return now | pre; 102 if (l == r) 103 { 104 Max[now] += Max[pre]; 105 pos[now] = l; 106 return now; 107 } 108 int mid = (l + r) >> 1; 109 if (lt[now] | lt[pre]) lt[now] = merge(lt[now], lt[pre], l, mid); 110 if (rt[now] | rt[pre]) rt[now] = merge(rt[now], rt[pre], mid + 1, r); 111 pushup(now); 112 return now; 113 } 114 } 115 116 int ans[N]; 117 void solve(int u) 118 { 119 erp(u) if (v != fa[u]) 120 { 121 solve(v); 122 SEG::T[u] = SEG::merge(SEG::T[u], SEG::T[v], 1, b[0]); 123 } 124 int Pos = SEG::pos[SEG::T[u]]; 125 ans[u] = Pos ? b[Pos] : 0; 126 } 127 128 int main() 129 { 130 while (scanf("%d%d", &n, &q) != EOF) 131 { 132 for (int i = 1, u, v; i < n; ++i) 133 { 134 scanf("%d%d", &u, &v); 135 G.add(u, v); 136 } 137 fa[1] = 0; DFS(1); getpos(1, 1); 138 for (int i = 1; i <= q; ++i) scanf("%d%d%d", x + i, y + i, z + i); Hash(); 139 for (int i = 1; i <= q; ++i) 140 { 141 int LCA = lca(x[i], y[i]); 142 SEG::update(SEG::T[x[i]], 1, b[0], z[i], 1); 143 SEG::update(SEG::T[y[i]], 1, b[0], z[i], 1); 144 SEG::update(SEG::T[LCA], 1, b[0], z[i], -1); 145 if (fa[LCA]) SEG::update(SEG::T[fa[LCA]], 1, b[0], z[i], -1); 146 } 147 solve(1); 148 for (int i = 1; i <= n; ++i) printf("%d\n", ans[i]); 149 } 150 return 0; 151 } 152