10 pts 线段树合并板子求调
  • 板块学术版
  • 楼主Anxiomgh
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/7/21 17:40
  • 上次更新2023/11/3 08:23:53
查看原帖
10 pts 线段树合并板子求调
415592
Anxiomgh楼主2023/7/21 17:40

RT,线段树合并裸题,不胜感激。

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;
#define ll long long

inline int read()
{
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
    return x * f;
}
const int MAXN = 1e5 + 10;
struct edge
{
    int nxt, to;
};
int head[MAXN], cnt; edge e[MAXN << 1];
void add_edge(int u, int v)
{
    e[++cnt].nxt = head[u];
    head[u] = cnt;
    e[cnt].to = v; 
}
int tot, root[MAXN], anc[MAXN][23], dep[MAXN], ans[MAXN];
struct segmentTree
{
    int u, val, ls, rs;
}tr[MAXN * 50];

void push_up(int x)
{
    if (tr[tr[x].ls].val >= tr[tr[x].rs].val) 
        tr[x].u = tr[tr[x].ls].u, tr[x].val = tr[tr[x].ls].val;
    else tr[x].u = tr[tr[x].rs].u, tr[x].val = tr[tr[x].rs].val;
}
void update(int &x, int p, int f, int l = 0, int r = 1e5)
{
    if (!x) x = ++tot;
    if (l == r)
    {
        tr[x].u = p; tr[x].val += f;
        return;
    }
    int mid = (l + r) >> 1;
    if (p <= mid) update(tr[x].ls, p, f, l, mid);
    else update(tr[x].rs, p, f, mid + 1, r);
    push_up(x);
}
int merge(int a, int b, int l = 0, int r = 1e5) // 将 b 合并到 a 
{
    if (!a) return b;
    if (!b) return a;
    if (l == r)
    {
        tr[a].val += tr[b].val;
        return a;
    }
    int mid = (l + r) >> 1;
    tr[a].ls = merge(tr[a].ls, tr[b].ls, l, mid);
    tr[a].rs = merge(tr[a].rs, tr[b].rs, mid + 1, r);
    push_up(a);
    return a;
} 
void dfs1(int x, int fa)
{
    for (int i = head[x]; i; i = e[i].nxt)
    {
        int v = e[i].to;
        if (v == fa) continue;
        dfs1(v, x);
        root[x] = merge(root[x], root[v]);
    }
    ans[x] = tr[root[x]].u;
    if (tr[root[x]].val == 0) ans[x] = 0;
}

void dfs2(int x, int fa, int d)
{
    dep[x] = d;
    for (int i = 1; i <= 20; i++)
        anc[x][i] = anc[anc[x][i - 1]][i - 1];
    for (int i = head[x]; i; i = e[i].nxt)
    {
        int v = e[i].to;
        if (v == fa) continue;
        anc[v][0] = x;
        dfs2(v, x, d + 1);
    }
}
int LCA(int x, int y)
{
    if (dep[x] > dep[y])
        swap(dep[x], dep[y]); // x 深度小,y 深度大 
    int tmp = dep[y] - dep[x];
    for (int i = 20; i >= 0; i--) // 跳 y 
        if (tmp & (1 << i)) y = anc[y][i];
    if (x == y) return x;
    for (int i = 20; i >= 0; i--)
        if (anc[x][i] != anc[y][i]) 
            x = anc[x][i], y = anc[y][i];
    return anc[x][0];
}
int main()
{
    int n, m;
    n = read(); m = read();
    for (int i = 2; i <= n; i++)
    {
        int a, b;
        a = read(); b = read();
        add_edge(a, b); add_edge(b, a);
    }
    dfs2(1, 0, 0);
    while (m--)
    {
        int x, y, z, lca;
        x = read(); y = read(); z = read();
        lca = LCA(x, y);
        update(root[x], z, 1); update(root[y], z, 1);
        update(root[lca], z, -1); update(root[anc[lca][0]], z, -1);
    }
    dfs1(1, 0);
    for (int i = 1; i <= n; i++)
        printf("%d\n", ans[i]);
    return 0;
}
2023/7/21 17:40
加载中...