动态开点权值线段树 线段树合并

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<int, pii> pipii;

ll LINF = 0x3F3F3F3F3F3F3F3FLL;

vector<int> G[100005];
int dep[100005];
int pa[100005][20];

void dfs1(int u, int p) {
    pa[u][0] = p;
    dep[u] = dep[p] + 1;
    for(int i = 1; i < 20; ++i)
        pa[u][i] = pa[pa[u][i - 1]][i - 1];
    for(int &v : G[u]) {
        if(v == p)
            continue;
        dfs1(v, u);
    }
    return;
}

int lca(int x, int y) {
    if(dep[x] < dep[y])
        swap(x, y);
    for(int i = 19; i >= 0; --i) {
        if(dep[pa[x][i]] >= dep[y])
            x = pa[x][i];
    }
    if(x == y)
        return x;
    for(int i = 19; i >= 0; --i) {
        if(pa[x][i] != pa[y][i]) {
            x = pa[x][i];
            y = pa[y][i];
        }
    }
    return pa[x][0];
}

int rt[100005];
int ls[100005 * 20];
int rs[100005 * 20];
int ct[100005 * 20];
int id[100005 * 20];
int top;

void Init() {
    top = 0;
    return;
}

int NewNode() {
    ++top;
    ls[top] = 0;
    rs[top] = 0;
    ct[top] = 0;
    id[top] = 0;
    return top;
}

void PushUp(int o) {
    if(ct[ls[o]] >= ct[rs[o]]) {
        ct[o] = ct[ls[o]];
        id[o] = id[ls[o]];
    } else {
        ct[o] = ct[rs[o]];
        id[o] = id[rs[o]];
    }
    if(ct[o] == 0)
        id[o] = 0;
    return;
}

void Add(int o, int l, int r, int p, int v) {
    if(l == r) {
        ct[o] += v;
        id[o] = l;
        return;
    }
    int m = (l + r) >> 1;
    if(p <= m) {
        if(ls[o] == 0)
            ls[o] = NewNode();
        Add(ls[o], l, m, p, v);
    }
    if(p >= m + 1) {
        if(rs[o] == 0)
            rs[o] = NewNode();
        Add(rs[o], m + 1, r, p, v);
    }
    PushUp(o);
    return;
}

void Merge(int u, int v, int l, int r) {
    if(l == r) {
        ct[u] += ct[v];
        id[u] = l;
        return;
    }
    int m = (l + r) >> 1;
    if(ls[v] != 0) {
        if(ls[u] == 0)
            ls[u] = ls[v];
        else
            Merge(ls[u], ls[v], l, m);
    }
    if(rs[v] != 0) {
        if(rs[u] == 0)
            rs[u] = rs[v];
        else
            Merge(rs[u], rs[v], m + 1, r);
    }
    PushUp(u);
    return;
}

int x[100005];
int y[100005];
int z[100005];

int Z[100005], Ztop;
vector<int> tag[100005];

void AddTag(int x, int y, int z) {
    tag[x].push_back(z);
    tag[y].push_back(z);
    int l = lca(x, y);
    tag[l].push_back(-z);
    if(pa[l][0] != 0)
        tag[pa[l][0]].push_back(-z);
    return;
}

int ans[100005];

void dfs2(int u, int p) {
    int maxct = 0, maxctid = 0;
    for(int &v : G[u]) {
        if(v == p)
            continue;
        dfs2(v, u);
        if(ct[rt[v]] > maxct) {
            maxct = ct[rt[v]];
            maxctid = v;
        }
    }
    rt[u] = (maxctid != 0) ? rt[maxctid] : NewNode();
    for(int &v : G[u]) {
        if(v == p || v == maxctid)
            continue;
        Merge(rt[u], rt[v], 1, Ztop);
    }
    for(int &z : tag[u]) {
        int p = z, v = 1;
        if(z < 0)
            p = -z, v = -1;
        Add(rt[u], 1, Ztop, p, v);
    }
    ans[u] = Z[id[rt[u]]];
    return;
}

void solve() {
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) {
        G[i].clear();
        tag[i].clear();
    }
    for(int i = 1; i <= n - 1; ++i) {
        int a, b;
        scanf("%d%d", &a, &b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    dfs1(1, 0);
    Ztop = 0;
    for(int i = 1; i <= m; ++i) {
        scanf("%d%d%d", &x[i], &y[i], &z[i]);
        Z[++Ztop] = z[i];
    }
    sort(Z + 1, Z + 1 + Ztop);
    Ztop = unique(Z + 1, Z + 1 + Ztop) - (Z + 1);
    for(int i = 1; i <= m; ++i) {
        z[i] = lower_bound(Z + 1, Z + 1 + Ztop, z[i]) - Z;
        AddTag(x[i], y[i], z[i]);
    }
    dfs2(1, 0);
    for(int i = 1; i <= n; ++i)
        printf("%d\n", ans[i]);
    return;
}

int main() {
#ifdef LOCAL
    freopen("lyz.txt", "r", stdin);
#endif // LOCAL
    solve();
    return 0;
}
posted @ 2020-10-27 14:43  purinliang  阅读(103)  评论(0编辑  收藏  举报