P4556 [Vani有约会]雨天的尾巴 /[模板] 线段树合并
树上差分 + 线段树合并
以每个点为根节点建立一棵权值线段树记录now(当前最多的粮食的种类) 和 size(最多的粮食的数量)
每棵线段树的叶节点 的下标就是粮食的种类a
最后合并每棵权值线段树就好啦
#include <bits/stdc++.h>
using namespace std;
#define mid (l + r) / 2
const int N = 1e5 + 5;
int n, m, cnt, tot, t;
int to[N << 1], head[N], nex[N << 1];
int ans[N], deep[N], f[N][50];
int ls[N * 80], rs[N * 80], root[N], size[N * 80], now[N * 80];
void add(int x, int y) {
nex[++cnt] = head[x];
to[cnt] = y;
head[x] = cnt;
}
void dfs(int x, int dep) {
deep[x] = dep;
for(int i = 1; i <= t; i++)
f[x][i] = f[f[x][i - 1]][i - 1];
for(int i = head[x]; i; i = nex[i]) {
int y = to[i];
if(deep[y]) continue;
f[y][0] = x;
dfs(y, dep + 1);
}
}
int LCA(int x, int y) {
if(deep[x] > deep[y]) swap(x, y);
for(int i = t; i >= 0; i--)
if(deep[f[y][i]] >= deep[x]) y = f[y][i];
if(x == y) return x;
for(int i = t; i >= 0; i--)
if(f[y][i] != f[x][i]) x = f[x][i], y = f[y][i];
return f[x][0];
}
void up(int x) {
if(size[ls[x]] >= size[rs[x]])
size[x] = size[ls[x]], now[x] = now[ls[x]];
else size[x] = size[rs[x]], now[x] = now[rs[x]];
}
int merge(int x, int y, int l, int r) { // 合并操作
if(!x || !y) return x + y;
if(l == r) {
size[x] += size[y];
now[x] = l;
return x;
}
ls[x] = merge(ls[x], ls[y], l, mid);
rs[x] = merge(rs[x], rs[y], mid + 1, r);
up(x);
return x;
}
void change(int &u, int l, int r, int num, int k) {
if(!u) u = ++tot;
if(l == r) {
size[u] += k;
now[u] = l;
return ;
}
if(num <= mid) change(ls[u], l, mid, num, k);
else change(rs[u], mid + 1, r, num, k);
up(u);
}
void cacl(int x) { // 合并每一棵线段树
for(int i = head[x]; i; i = nex[i]) {
int y = to[i];
if(y == f[x][0]) continue;
cacl(y);
root[x] = merge(root[x], root[y], 1, N - 5);
}
if(size[root[x]] && now[root[x]]) ans[x] = now[root[x]];
else ans[x] = 0;
}
int main() {
ios :: sync_with_stdio(0);
cin >> n >> m;
t = (log(n) / log(2)) + 1;
for(int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
add(a, b);
add(b, a);
}
dfs(1, 1);
for(int i = 1; i <= m; i++) {
int x, y, z;
cin >> x >> y >> z;
int lca = LCA(x, y);
change(root[x], 1, N - 5, z, 1); // z <= 1e5
change(root[y], 1, N - 5, z, 1);
change(root[lca], 1, N - 5, z, -1);
change(root[f[lca][0]], 1, N - 5, z, -1);
}
cacl(1);
for(int i = 1; i <= n; i++) cout << ans[i] << endl;
return 0;
}