倍增求出祖先,\(\text{DSU}\)统计

本来想用树剖求\(K\)祖,来条链复杂度就假了

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <numeric>
#define R(a,b,c) for(register int a = (b); a <= (c); ++a)
#define nR(a,b,c) for(register int a = (b); a >= (c); --a)
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define MP make_pair
#ifdef QWQ
#define D_e_Line printf("\n------\n")
#define D_e(x) cerr << (#x) << " " << x << endl
#define C_e(x) cout << (#x) << " " << x << endl
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#define Pause() system("pause")
#include <cassert>
#define PASS fprintf(stderr, "Passing [%s] in LINE %d\n",__FUNCTION__,__LINE__)
#else
#define D_e_Line
#define D_e(x)
#define C_e(x)
#define FileOpen()
#define FileSave()
#define Pause()
#define PASS
#endif
using namespace std;
struct FastIO {
template<typename ATP> inline FastIO& operator >> (ATP &x) {
x = 0; int sign = 1; char c;
for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-') sign = -1;
while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
if(sign == -1) x = -x;
return *this;
}
} io;
template<typename ATP> inline ATP Max(ATP x, ATP y) {
return x > y ? x : y;
}
template<typename ATP> inline ATP Min(ATP x, ATP y) {
return x < y ? x : y;
}
template<typename ATP> inline ATP Abs(ATP x) {
return x < 0 ? -x : x;
}
#include <vector>
const int N = 1e5 + 7;
struct Edge {
int nxt, pre;
} e[N];
int head[N], cntEdge;
inline void add(int u, int v) {
e[++cntEdge] = (Edge){ head[u], v}, head[u] = cntEdge;
}
vector<pair<int, int>> q[N];
int dep[N], fa[N][19], siz[N], top[N], dfn[N], dfnIdx, rnk[N], son[N];
void DFS_First(int u, int father) {
dep[u] = dep[father] + 1, fa[u][0] = father, siz[u] = 1;
R(i,1,18){
if(fa[u][i - 1]) fa[u][i] = fa[fa[u][i - 1]][i - 1];
else break;
}
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
DFS_First(v, u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v;
}
}
void DFS_Second(int u, int Tp) {
top[u] = Tp, dfn[u] = ++dfnIdx, rnk[dfnIdx] = u;
if(!son[u]) return;
DFS_Second(son[u], Tp);
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
if(v != son[u]) DFS_Second(v, v);
}
}
inline int Father(int u, int K) {
// while(dep[u] - dep[top[u]] + 1 <= K){
// K -= dep[u] - dep[top[u]] + 1;
// u = fa[top[u]];
// }
// return rnk[dfn[u] - K]; while(K){
int now = 0;
while((1 << (now + 1)) <= K) ++now;
u = fa[u][now];
K -= 1 << now;
}
return u;
}
int tot[N];
bool big[N];
void Add(int u) {
++tot[dep[u]];
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
if(big[v]) continue;
Add(v);
}
}
void Del(int u) {
--tot[dep[u]];
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
if(big[v]) continue;
Del(v);
}
}
int ans[N], n;
void DSU(int u, bool flag) {
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
if(v == son[u]) continue;
DSU(v, 0);
}
if(son[u]) DSU(son[u], 1), big[son[u]] = true;
Add(u);
for(vector<pair<int, int>>::iterator it = q[u].begin(); it != q[u].end(); ++it){
if(it->first + dep[u] <= n + 1){
ans[it->second] = tot[it->first + dep[u]] - 1;
}
}
big[son[u]] = false;
if(!flag) Del(u);
}
int main() {
int Q;
io >> n;
R(i,1,n){
int fat;
io >> fat;
++fat;
add(fat, i + 1);
}
DFS_First(1, 0);
DFS_Second(1, 1);
// while(1){
// int x, K;
// io >> x >> K;
// ++x;
// cout << Father(x, K) - 1<< endl;
// }
io >> Q;
R(i,1,Q){
int x, K;
io >> x >> K;
++x;
x = Father(x, K);
if(x == 1){
continue;
}
// D_e(x - 1);
q[x].emplace_back(K, i);
}
DSU(1, 0); R(i,1,Q){
printf("%d ", ans[i]);
}
return 0;
}
/*
6
0 1 1 0 4 4
7
1 1
1 2
2 1
2 2
4 1
5 1
6 1
*/
/*
6
0 1 2 3 4 5
5 1
*/

CF208E Blood Cousins(DSU,倍增)的更多相关文章

  1. CF208E Blood Cousins

    Blood Cousins 题目描述 小C喜欢研究族谱,这一天小C拿到了一整张族谱. 小C先要定义一下k-祖先. x的1-祖先指的是x的父亲 x的k-祖先指的是x的(k-1)-祖先的父亲 小C接下来要 ...

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

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

  3. CF208E Blood Cousins 题解

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

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

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

  5. [cf contest246] E - Blood Cousins Return

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

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

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

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

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

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

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

  9. CF 246E. Blood Cousins Return [dsu on tree STL]

    题意: 一个森林,求k级后代中多少种不同的权值 用set维护每个深度出现的权值 一开始一直在想删除怎么办,后来发现因为当前全局维护的东西里都是当前子树里的,如果要删除那么当前一定是轻儿子,直接清空se ...

随机推荐

  1. 我熬夜读完这份“高分宝典”,竟4面拿下字节跳动offer

    前言 怎样的契机? 实际上,目前毕业已经两年时间了,在大学时就已经开始关注字节跳动的发展.一开始,我是电气自动化专业的,大二清楚目标之后就转计算机了,大四进了一家小型的互联网公司实习,具体就不说哪家了 ...

  2. 手把手教你 Docker搭建mysql并配置远程访问

    一.使用docker部署mysql 1.在docker中搜索要安装的mysql docker search mysql (这步其实可以跳过O(∩_∩)O哈哈~) 2.拉取mysql镜像 docker ...

  3. camunda BPM支持的开发和运行环境

    以Camunda7.13版本为例,介绍Camunda支持的开发运行环境. 一.支持的Java开发环境 • Java版本: 8 / 9 / 10 / 11 / 12 / 13 / 14• Springb ...

  4. 腾讯QQ快捷登陆

    腾讯QQ快捷 相关各语言对接qq快捷登录教程 [C#]QQ开放平台(QQ站外登录)_流程和源码示例 j2ee中实现QQ第三方登陆 web实现QQ第三方登录 asp.net网站接入QQ登录 php实现q ...

  5. 使用PowerShell下载文件

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月12日. 使用Invoke-WebRequest指令下载文件 [Net.ServicePointManager]::Securit ...

  6. 攻防世界pwn题:实时数据检测

    0x00:查看文件 一个32位的文件,canary.NX.PIE保护机制均关闭. 0x01:用IDA进行静态分析 程序很简单,输入一串字符(个数限制:512),然后再输出.最后根据key变量进行条件语 ...

  7. 1.2 操作系统的第二个功能——并发功能 -《zobolの操作系统学习札记》

    1.2 操作系统的第二个功能--并发功能 目录 1.2 操作系统的第二个功能--并发功能 问1:什么是并发功能?并发功能是必要的吗? 问2:并发功能必须要求拥有多核CPU吗? 问3:多核CPU和单核C ...

  8. C语言学习之我见-malloc和free内存申请及释放函数

    malloc函数负责向计算机申请确定大小的内存空间. free函数负责释放malloc的申请空间. (1)函数原型 void free(void *_Memory); void * malloc(si ...

  9. SpringBoot 整合文件上传 elment Ui 上传组件

    SpringBoot 整合文件上传 elment Ui 上传组件 本文章记录 自己学习使用 侵权必删! 前端代码 博主最近在学 elment Ui 所以 前端使用 elmentUi 的 upload ...

  10. Lua5.4源码剖析:二. 详解String数据结构及操作算法

    概述 lua字符串通过操作算法和内存管理,有以下优点: 节省内存. 字符串比较效率高.(比较哈希值) 问题: 相同的字符串共享同一份内存么? 相同的长字符串一定不共享同一份内存么? lua字符串如何管 ...