# 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];
16     void add(int u, int v)
17     {
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);
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  
View Code

posted @ 2018-12-14 16:19  Dup4  阅读(161)  评论(0编辑  收藏  举报