P4556 [Vani有约会]雨天的尾巴
题目大意
给一个\(n\)个节点的树,每次操作给\(x_i,y_i\)上的简单路径上的点增加一个\(z_i\)类型的粮食,最后求每个节点粮食数量最多的粮食类型是什么,支持离线。\(n \le 10^5\)
每个节点维护一个权值线段树,树上差分最后合并。
# include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int dep[N],son[N],f[N],top[N],siz[N];
int lc[N << 6],rc[N << 6];
int Max[N << 6],Tag[N << 6];
int M;
int rt[N << 6];
int X[N],Y[N],Z[N];
int ans[N];
int n,m;
vector <int> g[N];
int tot = 0;
void dfs1(int x)
{
siz[x] = 1;
for(int i = 0; i < g[x].size(); i++)
{
int v = g[x][i];
if(v != f[x])
{
f[v] = x;
dep[v] = dep[x] + 1;
dfs1(v);
siz[x] += siz[v];
if(siz[v] > siz[son[x]])
{
son[x] = v;
}
}
}
return;
}
void dfs2(int x,int _top)
{
top[x] = _top;
if(son[x])
{
dfs2(son[x],_top);
}
for(int i = 0; i < g[x].size(); i++)
{
int v = g[x][i];
if(v != f[x] && v != son[x])
{
dfs2(v,v);
}
}
return;
}
int LCA(int x,int y)
{
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x,y);
x = f[top[x]];
}
return dep[x] < dep[y] ? x : y;
}
void pushup(int root)
{
if(Max[lc[root]] >= Max[rc[root]])
{
Max[root] = Max[lc[root]];
Tag[root] = Tag[lc[root]];
}
else
{
Max[root] = Max[rc[root]];
Tag[root] = Tag[rc[root]];
}
if(!Max[root]) Tag[root] = 0;
return;
}
void update(int &root,int l,int r,int x,int delta)
{
if(!root) root = ++tot;
if(l == r)
{
Max[root] += delta;
Tag[root] = l;
return;
}
int mid = (l + r) >> 1;
if(x <= mid) update(lc[root],l,mid,x,delta);
if(x > mid) update(rc[root],mid + 1,r,x,delta);
pushup(root);
return;
}
int merge(int u,int v,int l,int r)
{
if(u == 0 || v == 0)
{
return u + v;
}
if(l == r)
{
Max[u] += Max[v];
Tag[u] = l;
return u;
}
int mid = (l + r) >> 1;
lc[u] = merge(lc[u],lc[v],l,mid);
rc[u] = merge(rc[u],rc[v],mid + 1,r);
pushup(u);
return u;
}
void Get_ans(int x)
{
for(int i = 0; i < g[x].size(); i++)
{
int v = g[x][i];
if(v != f[x])
{
Get_ans(v);
rt[x] = merge(rt[x],rt[v],1,M);
}
}
ans[x] = Tag[rt[x]];
return;
}
int main(void)
{
scanf("%d%d",&n,&m);
for(int i = 1; i < n; i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs1(1);
dfs2(1,1);
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d",&X[i],&Y[i],&Z[i]);
M = max(M,Z[i]);
}
for(int i = 1; i <= m; i++)
{
int _l = LCA(X[i],Y[i]);
update(rt[X[i]],1,M,Z[i],1);
update(rt[Y[i]],1,M,Z[i],1);
update(rt[_l],1,M,Z[i],-1);
if(f[_l]) update(rt[f[_l]],1,M,Z[i],-1) ;
}
Get_ans(1);
for(int i = 1; i <= n; i++)
{
printf("%d\n",ans[i]);
}
return 0;
}