Codeforces 208E - Blood Cousins(树上启发式合并)
208E - Blood Cousins
题意
给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor。多次查询,给出 u k,问有多少个与 u 具有相同 k-ancestor 的节点。
分析
设 rt 为 u 的 k-ancestor。问题可以转换成在以 rt 为根的子树下,有多少个节点的深度与 u 相同。
预处理出离 u 距离为 k 的祖先 rt 。
我们可以把所有的查询用向量存起来(祖先节点,要查询的节点的深度,对应查询的id),在遍历到某个祖先节点时,统计那个子树下,我们所要查询的某个节点深度的数量,直接去更新答案。也就是说子树的状态信息(数量信息)可以复用,也就是说可以套用 树上启发式合并。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
int n;
int fa[MAXN][20], son[MAXN], dep[MAXN], siz[MAXN];
int col[MAXN];
int cnt, head[MAXN];
struct Edge {
int to, next;
} e[MAXN << 1];
struct Ex {
int x, c;
};
vector<Ex> ex[MAXN];
void addedge(int u, int v) {
e[cnt].to = v; e[cnt].next = head[u]; head[u] = cnt++;
e[cnt].to = u; e[cnt].next = head[v]; head[v] = cnt++;
}
void dfs(int u) {
siz[u] = 1;
son[u] = 0;
for(int i = 1; i < 20; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
for(int i = head[u]; ~i; i = e[i].next) {
if(e[i].to != fa[u][0]) {
fa[e[i].to][0] = u;
dep[e[i].to] = dep[u] + 1;
dfs(e[i].to);
if(siz[e[i].to] > siz[son[u]]) son[u] = e[i].to;
siz[u] += siz[e[i].to];
}
}
}
int getAn(int u, int d) {
for(int i = 0; i < 20; i++) {
if(d >> i & 1) {
u = fa[u][i];
}
}
return u;
}
int vis[MAXN], ans[MAXN], C[MAXN];
void change(int u, int c) {
C[dep[u]] += c;
for(int i = head[u]; ~i; i = e[i].next) {
if(e[i].to != fa[u][0] && !vis[e[i].to]) change(e[i].to, c);
}
}
void dfs1(int u, int flg) {
for(int i = head[u]; ~i; i = e[i].next) {
if(e[i].to != fa[u][0] && e[i].to != son[u]) dfs1(e[i].to, 1);
}
if(son[u]) {
dfs1(son[u], 0);
vis[son[u]] = 1;
}
change(u, 1);
int sz = ex[u].size();
for(int i = 0; i < sz; i++) {
ans[ex[u][i].x] = C[ex[u][i].c];
}
if(son[u]) vis[son[u]] = 0;
if(flg) change(u, -1);
}
int main() {
scanf("%d", &n);
memset(head, -1, sizeof head);
cnt = 0;
for(int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
addedge(i, x);
}
dfs(0);
int m;
scanf("%d", &m);
for(int i = 0; i < m; i++) {
int x, y;
scanf("%d%d", &x, &y);
if(dep[x] - y <= 0) {
ans[i] = 1;
continue;
}
int anc = getAn(x, y);
ex[anc].push_back(Ex{i, dep[x]});
}
dfs1(0, 0);
for(int i = 0; i < m; i++) {
printf("%d%c", ans[i] - 1, " \n"[i == m - 1]);
}
return 0;
}
Codeforces 208E - Blood Cousins(树上启发式合并)的更多相关文章
- Codeforces 208E. Blood Cousins
传送门 题目大意: 小C喜欢研究族谱,这一天小C拿到了一整张族谱. 小C先要定义一下k-祖先. x的1-祖先指的是x的父亲 x的k-祖先指的是x的(k-1)-祖先的父亲 小C接下来要定义k-兄弟 x的 ...
- Codeforces 246E - Blood Cousins Return (树上启发式合并)
246E - Blood Cousins Return 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor,每个节点有名字,名字不唯一.多次查询,给出 u k ...
- Codeforces 600E - Lomsat gelral(树上启发式合并)
600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对 ...
- 神奇的树上启发式合并 (dsu on tree)
参考资料 https://www.cnblogs.com/zhoushuyu/p/9069164.html https://www.cnblogs.com/candy99/p/dsuontree.ht ...
- CF EDU - E. Lomsat gelral 树上启发式合并
学习:http://codeforces.com/blog/entry/44351 E. Lomsat gelral 题意: 给定一个以1为根节点的树,每个节点都有一个颜色,问每个节点的子树中,颜色最 ...
- dsu on tree (树上启发式合并) 详解
一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...
- CF 208E - Blood Cousins dfs序+倍增
208E - Blood Cousins 题目:给出一棵树,问与节点v的第k个祖先相同的节点数有多少个. 分析: 寻找节点v的第k个祖先,这不就是qtree2简化版吗,但是怎么统计该祖先拥有多少个深度 ...
- dsu on tree 树上启发式合并 学习笔记
近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...
- 树上启发式合并(dsu on tree)学习笔记
有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...
随机推荐
- js实现类bootstrap模态框动画
在pc端开发,模态框是一个很常用的插件,之前一直用的第三方插件,比如bootstrap,jQuery的模态框插件,最近还用了elementUI的.但是会发现其实动画效果都差不多,那么如何去实现这样一个 ...
- 容器基础(一): Docker介绍
IaaS IaaS阶段, 用户租借基础设施,但是还是需要像以前管理服务器那样,用脚本或者手工方式在这些机器上部署应用.这个过程中当然难免会碰到云端机器和本地机器环境不一致的问题.想想每一次同步不同机器 ...
- 爬虫:Scrapy9 - Feed exports
实现爬虫时最经常提到的需求就是能合适的保存爬取到的数据,或者说,生成一个带有爬取数据的“输出文件”(通常叫“输出 feed”),来供其它系统使用. Scrapy 自带了 Feed 输出,并且支持多种序 ...
- BZOJ3876 [Ahoi2014&Jsoi2014]支线剧情 【有上下界费用流】
题目 [故事背景] 宅男JYY非常喜欢玩RPG游戏,比如仙剑,轩辕剑等等.不过JYY喜欢的并不是战斗场景,而是类似电视剧一般的充满恩怨情仇的剧情.这些游戏往往 都有很多的支线剧情,现在JYY想花费最少 ...
- 虚拟机——vmtools安装出现Detected GCC binary at usr.bin.gcc.
在安装VMWare Tools遇到过这样一个问题 Searching for GCC... Detected GCC binary at "/usr/bin/gcc". The p ...
- 《c程序设计语言》读书笔记-5.9-指针转换天数和日期
#include "stdio.h" #include "stdlib.h" #include "string.h" static char ...
- TortoiseSVN里checkout depth各选项的含义
代表四种检出深度: 1.Fully recursive——全递归:检出完整的目录树,包含所有的文件或子目录.2.Immediate children,including folders——直接子节点, ...
- Java I/O 笔记
1. Java常用I/O类概述 2. 文件I/O 你可以根据该文件是二进制文件还是文本文件来选择使用FileInputStream(FileOutputStream)或者FileReader(File ...
- 生成DLL
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.R ...
- zlib编译不过(Error A2070)解决方法(转)
原文转自 http://dearymz.blog.163.com/blog/static/2056574200871010027435/ 1.zlib是个很牛的东东,从http://www.zlib. ...