BZOJ - 3307: 雨天的尾巴

咱可以差分一下,把$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 }

 

posted @ 2017-12-27 11:53  p0ny  阅读(168)  评论(0编辑  收藏  举报