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 = ;
while (c < '' || c > '') c = getchar();
while ('' <= c && c <= '') x = x * + c - , c = getchar();
}
int n, K, Q, siz[N], d[N], c[N], big[N], R;
int _S[N], tp, cok, dfn[N], fa[][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] = ;
d[x] = d[Fa] + ;
fa[][x] = Fa;
for (int i = ; ( << i) <= d[x]; ++i) fa[i][x] = fa[i - ][fa[i - ][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() - ; i >= ; --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, );
if (big[x])
dfs3(big[x], ), vis[big[x]] = ;
draw(x, );
while (R && a[R].x == x) ans[a[R].id] = c[a[R].k] - , --R;
if (big[x])
vis[big[x]] = ;
if (!is)
draw(x, -);
}
int find(int x, int k) {//倍增找k-祖先
for (int i = ; k && i >= ; --i)
if (k >= ( << i))
x = fa[i][x], k -= << i;
return x;
}
int main() {
read(n);
for (int i = , u; i <= n; ++i) read(u), g[u].push_back(i);
read(Q);
R = Q;
for (int i = ; i <= Q; ++i) read(a[i].x), read(a[i].k), a[i].id = i;
for (auto i : g[]) dfs1(i, ), _S[++tp] = i;
for (auto i : g[]) dfs2(i);
for (int i = , q; i <= Q; ++i) q = a[i].x, a[i].x = find(q, a[i].k), a[i].k = d[q];//询问转化
sort(a + , a + Q + , cmp);
for (int i = tp; i; --i) dfs3(_S[i], );//倒着dfs
for (int i = ; i <= Q; ++i) printf("%d ", ans[i]);
return ;
}

CF208E Blood Cousins的更多相关文章

  1. CF208E Blood Cousins 题解

    一个奇奇怪怪的复杂度很垃圾的线段树合并解法 通过分析可以发现,要找$x$的$k$辈兄弟,只需要找到$x$的$k$辈祖先,然后查找以该祖先为根的子树中和$x$深度相同的节点个数$-1$即可.也就是说,询 ...

  2. CF208E Blood Cousins(DSU,倍增)

    倍增求出祖先,\(\text{DSU}\)统计 本来想用树剖求\(K\)祖,来条链复杂度就假了 #include <cstring> #include <cstdio> #in ...

  3. CF 208E - Blood Cousins dfs序+倍增

    208E - Blood Cousins 题目:给出一棵树,问与节点v的第k个祖先相同的节点数有多少个. 分析: 寻找节点v的第k个祖先,这不就是qtree2简化版吗,但是怎么统计该祖先拥有多少个深度 ...

  4. [cf contest246] E - Blood Cousins Return

    [cf contest246] E - Blood Cousins Return time limit per test 3 seconds memory limit per test 256 meg ...

  5. Codeforces 246E - Blood Cousins Return (树上启发式合并)

    246E - Blood Cousins Return 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor,每个节点有名字,名字不唯一.多次查询,给出 u k ...

  6. Codeforces 208E - Blood Cousins(树上启发式合并)

    208E - Blood Cousins 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor.多次查询,给出 u k,问有多少个与 u 具有相同 k-ance ...

  7. Codeforces 246E Blood Cousins Return(树上启发式合并)

    题目链接 Blood Cousins Return #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) f ...

  8. 【CF208E】Blood Cousins

    题目大意:给定一个 N 个点的森林,M 个询问,每次询问对于点 u 来说,有多少个点和 u 有相同的 K 级祖先. 题解:线段树合并适合处理子树贡献的问题. 发现要回答这个询问在点 u 处计算很困难, ...

  9. CF 208E. Blood Cousins [dsu on tree 倍增]

    题意:给出一个森林,求和一个点有相同k级祖先的点有多少 倍增求父亲然后和上题一样还不用哈希了... #include <iostream> #include <cstdio> ...

随机推荐

  1. Linux性能优化从入门到实战:02 CPU篇:平均负载

    每次发现系统变慢时,我们通常做的第一件事,就是执行 top 或 uptime 命令: $ uptime 22:22:17 up 2 days, 20:14, 1 user, load average: ...

  2. PHP实现session共享

    通过修改PHP-FPM配置文件,实现session会话共享: - 配置PHP使用memcached服务器共享Session信息 - 客户端访问两台不同的后端Web服务器时,Session 信息一致 环 ...

  3. Wannafly挑战赛27 D绿魔法师

    链接Wannafly挑战赛27 D绿魔法师 一个空的可重集合\(S\),\(n\)次操作,每次操作给出\(x,k,p\),要求支持下列操作: 1.在\(S\)中加入\(x\). 2.求\[\sum_{ ...

  4. 01.helloworld--标签

    """参考网站:http://python.cocos2d.org/doc/programming_guide/index.html""" ...

  5. Python---基础---dict和set2

    2019-05-21 写一个程序来管理用户登陆系统的用户信息:登陆名字和密码,登陆用户账号建立后,已存在用户可以用登陆名字和密码重返系统,新用户不能用别人的用户名建立用户账号 ------------ ...

  6. [BZOJ1826] 缓存交换

    问题描述 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数据调入Cache.此时,如果Cache容量已满,则必须先从中删除一个. 例如,当 ...

  7. cocos2dx-Lua3.10版本使用cjson

    参考:https://blog.csdn.net/shimazhuge/article/details/79848199 1.首先将cjson加入到libluacocos2d工程(cjson目录:/f ...

  8. php怎么获取js的变量值

    使用php做网站的时候,经常需要我们与前端的页面进行交互,有时候我们还需要通过php来获得js变量中的值,这种情况我们可以通过在其中嵌入js代码的方式来获得这个变量. 首先我们创建一个test的php ...

  9. vue定义自定义事件方法、事件传值及事件对象

    1.自定义事件 例如v-on:click="run" 或者 @click="run" <template> <div id="app ...

  10. pytest相关问题解析

    1. 如果你想查询在你的环境下有哪些pytest的active plugin可以使用: py.test --traceconfig 会得到一个扩展的头文件名显示激活的插件和他们的名字.同时也会打印出当 ...