样例不过 5pts 求条
查看原帖
样例不过 5pts 求条
1004065
xuduang楼主2024/8/10 16:50

rt,快红温了/oh

可以不用在意注释。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 6e6 + 10;
const int M = 1e5 + 10;
int n, m;
namespace ra
{
int head[M << 1], ne[M << 1], to[M << 1], id;    
inline int read()
{
    int s = 0, w = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') w = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        s = (s << 3) + (s << 1) + (ch ^ 48);
        ch = getchar();
    }
    return s * w;
}
void add(int x, int y)
{
    to[++id] = y, ne[id] = head[x], head[x] = id;
}
//可爱快读建边
}
using namespace ra;
namespace LCA
{
int fa[M], dep[M], son[M], siz[M];
void dfs1(int u, int faa)
{
    fa[u] = faa;
    dep[u] = dep[faa] + 1;
    siz[u] = 1;
    for(int i = head[u]; i; i = ne[i])
    {
        int v = to[i];
        if(v == faa) continue;
        dfs1(v, u);
        siz[u] += siz[v];
        if(siz[v] > siz[son[u]]) son[u] = v;
    }
}
int top[M];
// int dfn[M], dn;
void dfs2(int u, int tp)
{
    top[u] = tp;
    // dfn[u] = ++dn;
    if(!son[u]) return ;
    dfs2(son[u], tp);
    for(int i = head[u]; i; i = ne[i])
    {
        int v = to[i];
        if(v == fa[u] || v == son[u]) continue;
        dfs2(v, v);
    }
}
int LCA(int x, int y)
{
    while(top[x] != top[y])
    {
        if(dep[top[x]] < dep[top[y]]) swap(x, y);
        x = fa[top[x]];
    }
    return (dep[x] < dep[y] ? x : y);
}
//可爱树剖LCA
}
using namespace LCA;
namespace segment_tree
{
int ck = 0;
/*
cnt:众数出现次数
num:众数(是哪个)
ch[0/1]:左右儿子
ck:新点编号
*/
int cnt[N], num[N];
int ch[N][3];
void push_up(int u)
{
    if(cnt[ch[u][0]] >= cnt[ch[u][1]]) cnt[u] = cnt[ch[u][0]], num[u] = num[ch[u][0]];
    else cnt[u] = cnt[ch[u][1]], num[u] = num[ch[u][1]];
    /*
    看左右儿子哪个众数更众数
    更新 次数 和 众数
    */
}
int change(int u, int l, int r, int x, int v)
{
    if(!u) u = ++ck;
    if(l == r)
    {
        cnt[u] += v;
        num[u] = l;
        return u;
    }
    int mid = (l + r) >> 1;
    if(x <= mid) ch[u][0] = change(ch[u][0], l, mid, x, v);
    else ch[u][1] = change(ch[u][1], mid + 1, r, x, v);
    push_up(u);
    return u;
    /*
    单点加 v
    朴素递归
    */
}
int merge(int x, int y, int l, int r)
{
    if(!x || !y) return x + y;
    if(x == y)
    {
        cnt[x] += cnt[y];
        num[x] = l;
        return x;
        //同上
    }
    int mid = (l + r) >> 1;
    ch[x][0] = merge(ch[x][0], ch[y][0], l, mid);
    ch[x][1] = merge(ch[x][1], ch[y][1], mid + 1, r);
    push_up(x);
    return x;
    /*
    把 Y 递归并到 X 上
    */
}
}
using namespace segment_tree;
int a[M], b[M], c[M], mc;//mc:max of c
int root[M], ans[M];
void dfs(int u, int fa)
{
    for(int i = head[u]; i; i = ne[i])
    {
        int v = to[i];
        if(v == fa) continue;
        dfs(v, u);
        root[u] = merge(root[u], root[v], 1, mc);
    }
    if(cnt[root[u]]) ans[u] = num[root[u]];
}
signed main()
{
    n = read(), m = read();
    for(int i = 1; i < n; i++)
    {
        int x = read(), y = read();
        add(x, y);
        add(y, x);
    }
    dfs1(1, 0);
    dfs2(1, 1);
    for(int i = 1; i <= m; i++)a[i] = read(), b[i] = read(), c[i] = read(), mc = max(mc, c[i]);
    for(int i = 1; i <= m; i++)
    {
        /*
        差分的把 a-b 的路径上的点++
        (a-root)++, (b-root)++
        (lca-root)--, (fa[lca]-root)--
        */
        int lca = LCA::LCA(a[i], b[i]);
        root[a[i]] = change(root[a[i]], 1, mc, c[i], 1);
        root[b[i]] = change(root[b[i]], 1, mc, c[i], 1);
        root[lca] = change(root[lca], 1, mc, c[i], -1);
        lca = fa[lca];//变为父亲
        if(!lca) continue;
        root[lca] = change(root[lca], 1, mc, c[i], -1);
    }
    dfs(1, 0);//跑答案
    for(int i = 1; i <= n; i++) printf("%lld\n", ans[i]);
    return 0;
}
2024/8/10 16:50
加载中...