[CF191C] Fools and Roads - 树上差分,LCA

Description

给出一棵树,给出 m 对点,每对点之间的路径全部加一,最后输出每条边的值。

Solution

剖分求 LCA,然后差分

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1e6 + 5;

vector<int> g[N];
int n, siz[N], wson[N], dep[N], top[N], fa[N], sum[N];

void dfs1(int p, int from)
{
    siz[p] = 1;
    for (int q : g[p])
    {
        if (q == from)
            continue;
        dep[q] = dep[p] + 1;
        fa[q] = p;
        dfs1(q, p);
        siz[p] += siz[q];
        if (siz[q] > siz[wson[p]])
            wson[p] = q;
    }
}

void dfs2(int p, int from)
{
    if (wson[p])
    {
        int q = wson[p];
        top[q] = top[p];
        dfs2(q, p);
    }
    for (int q : g[p])
    {
        if (q == from || q == wson[p])
            continue;
        top[q] = q;
        dfs2(q, p);
    }
}

int lca(int p, int q)
{
    while (top[p] != top[q])
    {
        if (dep[top[p]] < dep[top[q]])
            swap(p, q);
        p = fa[top[p]];
    }
    if (dep[p] > dep[q])
        return q;
    else
        return p;
}

void puttag(int p, int val)
{
    sum[p] += val;
}

void dfs3(int p, int from)
{
    for (int q : g[p])
    {
        if (q == from)
            continue;
        dfs3(q, p);
        sum[p] += sum[q];
    }
}

signed main()
{
    ios::sync_with_stdio(false);

    cin >> n;
    vector<pair<int, int>> edge(n + 2);
    for (int i = 1; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
        edge[i] = {x, y};
    }

    dfs1(1, 0);
    top[1] = 1;
    dfs2(1, 0);

    int k;
    cin >> k;
    for (int i = 1; i <= k; i++)
    {
        int x, y;
        cin >> x >> y;
        int l = lca(x, y);
        puttag(x, +1);
        puttag(y, +1);
        puttag(l, -2);
    }

    dfs3(1, 0);

    for (int i = 1; i < n; i++)
    {
        auto [x, y] = edge[i];
        if (dep[x] > dep[y])
            cout << sum[x] << " ";
        else
            cout << sum[y] << " ";
    }
}

相关文章:

  • 2022-12-23
  • 2021-06-04
  • 2021-09-25
  • 2021-06-03
  • 2021-11-03
  • 2022-12-23
  • 2018-10-29
  • 2021-08-07
猜你喜欢
  • 2022-12-23
  • 2022-01-25
  • 2022-02-27
  • 2022-12-23
  • 2021-06-28
  • 2021-08-06
  • 2022-12-23
相关资源
相似解决方案