• CF208E Blood Cousins


    Blood Cousins

    题目描述

    小C喜欢研究族谱,这一天小C拿到了一整张族谱。

    小C先要定义一下k-祖先。

    • x的1-祖先指的是x的父亲
    • x的k-祖先指的是x的(k-1)-祖先的父亲

    小C接下来要定义k-兄弟

    • xx的k-兄弟指的是与x的k-祖先相同的人
    • 如果不存在k-祖先那么x没有k-兄弟

    小C想问问你,xx到底有多少k-兄弟?小C打算问QQ次这样的问题。

    输入格式

    第一行11个数nn,表示族谱中的人数,从11开始编号。

    接下来一行nn个数,第ii个数r_iri指的是ii的父亲,如果为0,则可能是因为族谱数据不全,它在族谱中没有父亲。

    接下来11个数QQ,表示小C问题的个数。

    接下来QQ行,每行两个数x, kx,k,表示一个问题。

    输出格式

    输出一行QQ个数,表示问题的答案。


    处理询问的话,可以把询问按dfs序排序,然后倒着处理

    对于每个询问$(x,k)$,可以转化成:在以x的k-祖先为根的子树上,深度与$x$相同的点的个数

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    #define N 100005
    void read(int &x) {
        char c = getchar();
        x = 0;
        while (c < '0' || c > '9') c = getchar();
        while ('0' <= c && c <= '9') x = x * 10 + c - 48, c = getchar();
    }
    int n, K, Q, siz[N], d[N], c[N], big[N], R;
    int _S[N], tp, cok, dfn[N], fa[17][N], ans[N];
    struct Data {
        int x, k, id;
    } a[N];
    bool cmp(Data A, Data B) { return dfn[A.x] < dfn[B.x]; }
    bool vis[N];
    vector<int> g[N];
    
    void dfs1(int x, int Fa) {
        siz[x] = 1;
        d[x] = d[Fa] + 1;
        fa[0][x] = Fa;
        for (int i = 1; (1 << i) <= d[x]; ++i) fa[i][x] = fa[i - 1][fa[i - 1][x]];
        for (auto i : g[x]) {
            dfs1(i, x);
            siz[x] += siz[i];
            if (siz[i] > siz[big[x]])
                big[x] = i;
        }
    }
    void dfs2(int x) {//dfs序给定后,后面的遍历全部倒着来
        dfn[x] = ++cok;
        if (big[x])
            dfs2(big[x]);
        for (int i = g[x].size() - 1; i >= 0; --i)
            if (g[x][i] != big[x])
                dfs2(g[x][i]);
    }
    void draw(int x, int k) {
        c[d[x]] += k;
        for (auto i : g[x])
            if (!vis[i])
                draw(i, k);
    }
    void dfs3(int x, bool is) {
        for (auto i : g[x])
            if (i != big[x])
                dfs3(i, 0);
        if (big[x])
            dfs3(big[x], 1), vis[big[x]] = 1;
        draw(x, 1);
        while (R && a[R].x == x) ans[a[R].id] = c[a[R].k] - 1, --R;
        if (big[x])
            vis[big[x]] = 0;
        if (!is)
            draw(x, -1);
    }
    int find(int x, int k) {//倍增找k-祖先
        for (int i = 16; k && i >= 0; --i)
            if (k >= (1 << i))
                x = fa[i][x], k -= 1 << i;
        return x;
    }
    int main() {
        read(n);
        for (int i = 1, u; i <= n; ++i) read(u), g[u].push_back(i);
        read(Q);
        R = Q;
        for (int i = 1; i <= Q; ++i) read(a[i].x), read(a[i].k), a[i].id = i;
        for (auto i : g[0]) dfs1(i, 0), _S[++tp] = i;
        for (auto i : g[0]) dfs2(i);
        for (int i = 1, q; i <= Q; ++i) q = a[i].x, a[i].x = find(q, a[i].k), a[i].k = d[q];//询问转化
        sort(a + 1, a + Q + 1, cmp);
        for (int i = tp; i; --i) dfs3(_S[i], 0);//倒着dfs
        for (int i = 1; i <= Q; ++i) printf("%d ", ans[i]);
        return 0;
    }
  • 相关阅读:
    嵌入式开发之zynq——zynq开发环境搭建
    嵌入式开发之zynq——赛灵思的一款两a9加一fpga芯片的开发板
    数据结构和算法的选择
    找工作看准网
    健康情感之招聘---图像算法工程师
    grafana 邮件报警
    ELK logstash邮件报警
    grafana + influxdb + telegraf
    centos 6.5 上安装使用upsource
    ELK 中的elasticsearch 集群的部署
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10946226.html
Copyright © 2020-2023  润新知