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 ...
随机推荐
- 算法のLowLow三人行
点击
- 第一天docker入门
[01 入门] docker 最核心为三部分组成 镜像,仓库和容器 镜像:一个只读的模板 仓库:代码仓库,镜像的集合 容器:镜像的实例化进程 我们可以这样理解 容器就是一个沙箱,docker利用容器运 ...
- Python学习-django-ModelForm组件
ModelForm a. class Meta: model, # 对应Model的 fields=None, # 字段 exclude=None, # 排除字段 labels=None, # 提示信 ...
- springboot04 Ajax json Jquery
一.Ajax 1.同步&异步请求 在所有的请求响应交互世界里,我们有通常会划分出来两种形态的请求, 一种是同步请求.另一种是异步请求 .比如注册.登录.添加数据等等这些请求执行的就是同步请求, ...
- 网络--NAT技术
一.概述 1.简介 NAT英文全称是“Network Address Translation”,中文意思是“网络地址转换”,它是一个IETF(Internet Engineering Task For ...
- Problem 1036 四塔问题
Accept: 590 Submit: 1506Time Limit: 1000 mSec Memory Limit : 32768 KB Problem Description “汉诺 ...
- 二、vue响应式对象
Object.defineProperty Object.defineProperty 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象,先来看一下它的语法: Obj ...
- 没有外网情况下linux安装mysql
首先linux要使用局域网 环境要求:局域网, windows系统, linux系统, mysql安装包mysql.tar.gz 注意:32位操作系统用32位安装包,64位系统用64位安装包,不 ...
- Educational Codeforces Round 42 (Rated for Div. 2) A
A. Equator time limit per test 2 seconds memory limit per test 256 megabytes input standard input ou ...
- 关于js的addEventListener 和一些常用事件
element.addEventListener(<event-name>, <callback>, <use-capture>);document.addEven ...