zoukankan      html  css  js  c++  java
  • [CF208E] Blood Cousins

    [CF208E] Blood Cousins - dsu on tree, LCA

    Description

    给你一片森林,每次询问一个点与多少个点拥有共同的 K 级祖先。

    Solution

    dsu on tree

    首先,求出一个点的 k 级祖先,并且把询问挂在他身上,问的就是这个点 p 子树内有多少个深度为 d 的点

    在 dfs 过程中,对每个点,递归处理各个孩子,同时保留其重孩子的贡献,再加上轻孩子的贡献,得到自身的贡献

    总结一下我们需要支持哪些事情:求 k 级祖先(倍增处理),将询问挂在祖先上,树上启发式合并处理所有询问

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    const int N = 1e5 + 5;
    
    ///////////////////////////////////////////////////
    
    vector<int> g[N];
    int n, wson[N], dep[N], siz[N], fa[N][20], ans[N];
    
    ///////////////////////////////////////////////////
    
    vector<pair<int, int>> question[N];
    
    ///////////////////////////////////////////////////
    
    int bucket[N];
    vector<int> record;
    
    void add(int p)
    {
        bucket[p]++;
        record.push_back(p);
    }
    
    void dec(int p)
    {
        bucket[p]--;
    }
    
    void clr()
    {
        for (auto i : record)
            dec(i);
        record.clear();
    }
    
    //////////////////////////////////////////////////
    
    int get_kth_father(int p, int k)
    {
        for (int i = 19; i >= 0; i--)
            if ((k >> i) & 1)
                p = fa[p][i];
        return p;
    }
    
    void make_question(int p, int k, int id)
    {
        int par = get_kth_father(p, k);
        if (par)
        {
            question[par].push_back(make_pair(dep[p], id));
        }
    }
    
    void dfs_pre(int p)
    {
        siz[p] = 1;
        for (int q : g[p])
        {
            dep[q] = dep[p] + 1;
            fa[q][0] = p;
            for (int j = 1; j < 20; j++)
                fa[q][j] = fa[fa[q][j - 1]][j - 1];
            dfs_pre(q);
            siz[p] += siz[q];
            if (siz[wson[p]] < siz[q])
                wson[p] = q;
        }
    }
    
    void dfs_add(int p)
    {
        add(dep[p]);
        for (int q : g[p])
            dfs_add(q);
    }
    
    void dfs(int p)
    {
        for (int q : g[p])
        {
            if (q == wson[p])
                continue;
            dfs(q);
            clr();
        }
        if (wson[p])
        {
            dfs(wson[p]);
        }
        for (int q : g[p])
        {
            if (q == wson[p])
                continue;
            dfs_add(q);
        }
        add(dep[p]);
    
        // cout << "p=" << p << endl;
        // for (int i = 0; i <= 10; i++)
        //     cout << bucket[i] << " ";
        // cout << endl;
        for (auto [depth, id] : question[p])
        {
            // cout << " question: " << depth << " " << id << endl;
            ans[id] = bucket[depth] - 1;
        }
    }
    
    ///////////////////////////////////////////////////
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
            int r;
            cin >> r;
            g[r].push_back(i);
        }
    
        dfs_pre(0);
    
        int m;
        cin >> m;
        for (int i = 1; i <= m; i++)
        {
            int v, k;
            cin >> v >> k;
            make_question(v, k, i);
        }
    
        dfs(0);
    
        for (int i = 1; i <= m; i++)
            cout << ans[i] << " ";
    }
    
  • 相关阅读:
    .net core读取appsettings.config中文乱码问题
    vs2017错误:当前页面的脚本发生错误
    VS Code中无法识别npm命令
    Visual Studio报错/plugin.vs.js,行:1074,错误:缺少标识符、字符串或数字
    记录一次在生成数据库服务器上出现The timeout period elapsed prior to completion of the operation or the server is not responding.和Exception has been thrown by the target of an invocation的解决办法
    Java集合框架
    java hash表
    Java Dictionary 类存储键值
    java数据结构 栈stack
    java封装
  • 原文地址:https://www.cnblogs.com/mollnn/p/14348852.html
Copyright © 2011-2022 走看看