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  
View Code

 

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