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] << " ";
    }
    
  • 相关阅读:
    js获取客户端time,cookie,url,ip,refer,user_agent信息:
    生成springboot docker镜像 并上传到阿里云镜像厂库
    install pymongo,mysql
    No module named MYSQLdb 问题解决
    CentOS7下安装python-pip
    task_payment_byonlinedown
    SPLIT_STR
    通过 Composer 安装 Laravel 安装器
    laravel Faker-1.faker假数据
    laravel-admin安装时执行php arisan admin:install 命令时报SQLSTATE[42000]: Syntax error or acce ss violation: 1071 Specified key was too long; max key length is 1000 bytes
  • 原文地址:https://www.cnblogs.com/mollnn/p/14348852.html
Copyright © 2011-2022 走看看