LCA + 树上差分模板

https://www.luogu.com.cn/problem/P3258

点差分

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 3e5 + 10;
int a[N];
int head[N], nxt[N * 2], to[N * 2], E;
int w[N];
int c[N];
int f[N][20]; // 2 ^ 18
int dep[N];
void add(int x, int y)
{
    to[E] = y;
    nxt[E] = head[x];
    head[x] = E++;
}
void dfs(int u, int fa)
{
    for (int i = head[u]; i != -1; i = nxt[i])
    {
        int v = to[i];
        if (v == fa)continue;
        dep[v] = dep[u] + 1;
        f[v][0] = u;
        for (int i = 1; i <= 18; i++)
            f[v][i] = f[f[v][i - 1]][i - 1];
        dfs(v, u);
    }
}
int lca(int x, int y)
{
    if (dep[x] < dep[y])swap(x, y);
    int d = dep[x] - dep[y];
    for (int i = 18; i >= 0; i--)
        if (d & (1<<i))
            x = f[x][i];
    if (x == y)return x;
    for (int i = 18; i >= 0; i--)
        if (f[x][i] != f[y][i])
            x = f[x][i], y = f[y][i];
    return f[x][0];
}
void dfs1(int u, int fa)
{
    for (int i = head[u]; i != -1; i = nxt[i])
    {
        int v = to[i];
        if (v == fa)continue;
        dfs1(v, u);
        c[u] += c[v];
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    mt19937_64 mrand(time(0));
    memset(head, -1, sizeof(head));
    int n; cin >> n;
    for (int i = 1; i <= n; i++)cin >> a[i];
    for (int i = 1; i < n; i++)
    {
        int x, y; cin >> x >> y;
        add(x, y), add(y, x);
    }
    dfs(a[1], -1);
    int last = a[1];
    for (int i = 2; i <= n; i++)
    {
        c[a[i]]++; c[last]++;
        int l = lca(a[i], last);
        c[l]--; c[f[l][0]]--;
        last = a[i];
    }
    dfs1(a[1], -1);
    for (int i = 2; i <= n; i++)c[a[i]]--;
    for (int i = 1; i <= n; i++)cout << c[i] << '\n';
    return 0;
}
posted @ 2025-05-31 15:36  闫柏军  阅读(8)  评论(0)    收藏  举报