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;
}
posted @ 2020-10-24 09:33  luyiming123  阅读(112)  评论(0编辑  收藏  举报