1. 程式人生 > >BZOJ - 3307: 雨天的尾巴

BZOJ - 3307: 雨天的尾巴

cassert ati back amp for node size return static

咱可以差分一下,把$u-v$這條路徑上的$z$都加$1$變成$u$和$v$的$z$加$1$,$lca$和$fa_{lca}$的$z$減$1$。

用線段樹實現最大值的查詢,最後$dfs$自底向上一路合並並查詢即可。

先開始線段樹數組開小了,$RE$了一次。

  1 #include<cassert>
  2 #include<cstdio>
  3 #include<vector>
  4 #include<iostream>
  5 #include<algorithm>
  6 #define pb push_back
  7 using
namespace std; 8 inline char nc() { 9 static char b[1<<14],*s=b,*t=b; 10 return s==t&&(t=(s=b)+fread(b,1,1<<14,stdin),s==t)?-1:*s++; 11 } 12 inline void read(int &x) { 13 char b = nc(); x = 0; 14 for (; !isdigit(b); b = nc()); 15 for (; isdigit(b); b = nc()) x = x * 10
+ b - 0; 16 } 17 const int N = 100010, M = 6000000; 18 int ls[M], rs[M], mx[M], A, rt[N]; 19 int n, m, sz[N], fa[N], dep[N], son[N], top[N], H, h[N], ans[N], r[N]; 20 vector < int > g[N]; 21 inline void ae(int u, int v) { 22 g[u].pb(v); g[v].pb(u); 23 } 24 void dfs(int u) { 25 sz[u] = 1
; 26 for (int v, i = 0; i < g[u].size(); ++i) 27 if ((v = g[u][i]) != fa[u]) { 28 fa[v] = u; dep[v] = dep[u] + 1; 29 dfs(v); sz[u] += sz[v]; 30 if (sz[son[u]] < sz[v]) son[u] = v; 31 } 32 } 33 void dfs(int u, int tp) { 34 top[u] = tp; if (son[u]) dfs(son[u], tp); 35 for (int v, i = 0; i < g[u].size(); ++i) 36 if (v = g[u][i], v != son[u] && v != fa[u]) dfs(v, v); 37 } 38 int findLca(int a, int b) { 39 for (; top[a] != top[b]; a = fa[top[a]]) 40 if (dep[top[a]] < dep[top[b]]) swap(a, b); 41 return dep[a] < dep[b] ? a : b; 42 } 43 struct Node { 44 int u, v, z; 45 inline int init() { 46 read(u); read(v); read(z); return z; 47 } 48 } q[N]; 49 inline int idx(int x) { 50 return lower_bound(h + 1, h + 1 + H, x) - h; 51 } 52 #define lson l, m, ls[o] 53 #define rson m + 1, r, rs[o] 54 inline void upd(int o) { 55 mx[o] = max(mx[ls[o]], mx[rs[o]]); 56 } 57 void add(int p, int x, int l, int r, int &o) { 58 if (!o) o = ++A; 59 if (l == r) return mx[o] += x, void(); 60 int m = (l + r) >> 1; 61 if (p <= m) add(p, x, lson); else add(p, x, rson); 62 upd(o); 63 } 64 int query(int l, int r, int o) { 65 if (l == r) return l; 66 int m = (l + r) >> 1; 67 if (mx[ls[o]] >= mx[rs[o]]) return query(lson); 68 else return query(rson); 69 } 70 int merge(int x, int y, int l, int r) { 71 if (!x) return y; if (!y) return x; 72 if (l == r) return mx[x] += mx[y], x; 73 int m = (l + r) >> 1; 74 ls[x] = merge(ls[x], ls[y], l, m); 75 rs[x] = merge(rs[x], rs[y], m + 1, r); 76 upd(x); return x; 77 } 78 void getans(int u) { 79 for (int v, i = 0; i < g[u].size(); ++i) { 80 if ((v = g[u][i]) != fa[u]) 81 getans(v), rt[u] = merge(rt[u], rt[v], 1, H); 82 } if (mx[rt[u]]) ans[u] = r[query(1, H, rt[u])]; 83 } 84 int main() { 85 read(n); read(m); 86 for (int u, v, i = 1; i < n; ++i) 87 read(u), read(v), ae(u, v); 88 dfs(1); dfs(1, 1); 89 for (int i = 1; i <= m; ++i) h[i] = q[i].init(); 90 sort(h + 1, h + 1 + m); H = unique(h + 1, h + 1 + m) - h - 1; 91 for (int i = 1; i <= H; ++i) r[i] = h[i]; 92 for (int u, v, z, l, i = 1; i <= m; ++i) { 93 u = q[i].u, v = q[i].v, z = idx(q[i].z); l = findLca(u, v); 94 add(z, 1, 1, H, rt[u]); add(z, 1, 1, H, rt[v]); 95 add(z, -1, 1, H, rt[l]); 96 if (fa[l]) add(z, -1, 1, H, rt[fa[l]]); 97 } getans(1); 98 for (int i = 1; i <= n; ++i) printf("%d\n", ans[i]); 99 return 0; 100 }

BZOJ - 3307: 雨天的尾巴