妙妙线段树+DFS序判断子孙节点,但似乎还可以树链剖分?(CF Div3 909 G)
G. Unusual Entertainment
原题链接:https://codeforces.com/contest/1899/problem/G
题目大意:
给定一棵树,根节点为1,给定一个\(1\) ~ \(n\) 的排列 \(p\) ,\(q\) 次查询,每次给出 \(l\) 和 \(r\) 还有 \(x\),查询序列 \(p\) 的 \(l\) ~ \(r\) 范围内是否存在节点编号 \(y\) 为 \(x\) 的子孙节点,如果有则输出 \(YES\),否则输出 \(NO\)。
思路:
解法一(官方题解做法):
\(x\) 的子孙节点 \(y\) 在 \(dfs\) 时,入栈时间 \(tin[y]\) 出栈时间 \(tout[y]\),满足:\(tin[x] < tin[y]\) \(tout[x] >= tout[y]\),每次查询序列\(p\) 的 \(l\) ~ \(r\) 中是否存在 \(x\) 的子孙节点就转化为查询序列 \(p\) 的 \(l\) ~ \(r\) 中对应的 \(y = p[i], l <= i <= r\),是否有 \(tin[x] < tin[y]\) and \(tout[x] >= tout[y]\)。构建序列\(a\) 且 \(a[i] = tin[p[i]]\),那么原问题就转化为在序列\(a\) 的 \(l\) ~ \(r\) 中对应的 \(tin[x] <= a[i] <= tout[x]\) 个数的查询。然后就可以维护一个线段树,这里的线段树相当于是一个存储过程的归并排序,每次查询相应区间上的个数。线段树的时空间复杂度均为 \(O(nlgn)\) ,每次通过二分查找即可确定个数。
总时间复杂度为:\(O(nlgn) + O(q*lg(n)^2)\) -> 二分的lg与线段树的lg相乘
解法二(树链剖分)
对整棵树进行树剖后,父节点 \(x\) 的子节点的序列一定在其之后的 \(id[x]+1\) 到 \(id[x]+sz[x]-1\) 之间,利用序列 \(p\) 我们可以得到对应节点编号 \(y\) 在其中的位置 \(py\),将其视为 \(nw[id[y]]\) 就可以利用这个信息去建立线段树,处理方式与方法一相同,也是查询个数,但查询的是 \(x\) 的子孙节点中位置信息在 \(l\) ~ \(r\)之间的个数。
代码:
方法一:
#include <bits/stdc++.h>
using namespace std;
#define TII tuple<int, int, int>
#define all(x) x.begin(), x.end()
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5 + 10, M = 2e5 + 10, K = 20, mod = 998244353;
const int INF = 0x3f3f3f3f;
const ll INF_L = 1e15;
int n, m;
vector<vector<int>> e;
int timestamp;
vector<int> tin, tout;
struct Node{
int l, r;
vector<int> v;
}tr[4 * N];
inline void add(int a, int b){ e[a].push_back(b); }
void dfs(int x, int father){
tin[x] = timestamp ++;
for(auto y : e[x]){
if(y == father) continue;
dfs(y, x);
}
tout[x] = timestamp;
}
void build(int u, int l, int r, vector<int> &a){
tr[u].v.clear();
if(l == r) tr[u] = {l, r, {a[l]}};
else{
tr[u] = {l, r};
int mid = l + r >> 1;
build(u << 1, l, mid, a), build(u << 1 | 1, mid + 1, r, a);
merge(all(tr[u << 1].v), all(tr[u << 1 | 1].v), back_inserter(tr[u].v));
}
}
int count(int u, int l, int r, int low, int up){
if(tr[u].l >= l && tr[u].r <= r) return lower_bound(all(tr[u].v), up) - lower_bound(all(tr[u].v), low);
else{
int mid = tr[u].l + tr[u].r >> 1;
int res = 0;
if(l <= mid) res += count(u << 1, l, r, low, up);
if(r > mid) res += count(u << 1 | 1, l, r, low, up);
return res;
}
}
void solve()
{
int q;
cin >> n >> q;
e.assign(n + 1, vector<int>());
for(int i = 1; i < n; i ++){
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
timestamp = 0;
tin.resize(n + 1);
tout.resize(n + 1);
dfs(1, -1);
vector<int> p(n + 1);
for(int i = 1; i <= n; i ++) cin >> p[i];
vector<int> a(n + 1);
for(int i = 1; i <= n; i ++) a[i] = tin[p[i]];
build(1, 1, n, a);
while(q --){
int l, r, x;
cin >> l >> r >> x;
if(count(1, l, r, tin[x], tout[x])) cout << "Yes\n";
else cout << "No\n";
}
}
int main()
{
cin.tie(0)->sync_with_stdio(false);
cout.tie(0);
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}
方法二(待补)
妙妙线段树+DFS序判断子孙节点,但似乎还可以树链剖分?(CF Div3 909 G)的更多相关文章
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- Codeforces 343D WaterTree - 线段树, DFS序
Description Translated by @Nishikino_Maki from Luogu 行吧是我翻的 Mad scientist Mike has constructed a roo ...
- BZOJ_3252_攻略_线段树+dfs序
BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...
- 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序
题目大意 Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...
- 【bzoj4817】树点涂色 LCT+线段树+dfs序
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- S - Query on a tree HDU - 3804 线段树+dfs序
S - Query on a tree HDU - 3804 离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...
- 瞎写的树dfs序
这里枚举了树的DFS序来解决树上问题的多个板子,自己最好多看看. ↓改↓ ↓求↓ 点 点 ————————>>>这个就算了 点 树 简单, BIT 点 链 重点! 树 树 简单, 线 ...
- 51 nod 1681 公共祖先 (主席树+dfs序)
1681 公共祖先 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另 ...
- 【BZOJ】3991: [SDOI2015]寻宝游戏 虚树+DFS序+set
[题意]给定n个点的带边权树,对于树上存在的若干特殊点,要求任选一个点开始将所有特殊点走遍后返回.现在初始没有特殊点,m次操作每次增加或减少一个特殊点,求每次操作后的总代价.n,m<=10^5. ...
- 【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序
[BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n n ...
随机推荐
- jQuery validate验证表单隐藏域
function validInfoForm(){ return $("#form_password").validate({ ignore : ...
- 八米云高收益PCDN-N1设备重要通知
八米云单价: 电联2400元/G/月 移动1500元/G/月 新上机设备[必须使用新镜像]上机!否则无业务下发! 再次强调!如6.18日后台镜像更新后–还在使用旧镜像新上机,请务必于[6月30日]前用 ...
- Windows下快捷方式 (*.lnk) 的使用技巧整理
日常应用中,许多软件都会在安装过程最后一步添加多个命令,针对其应用创建快捷方式发送到桌面以及快速启动栏和开始菜单,供人们快速找到并打开.在我的使用习惯中也会将诸多常用的应用右键-发送到-桌面快捷方式来 ...
- 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
学习编程之初就常被告诫:"永远不要相信用户的输入",但实际编码中,可能因为各种原因而忽略这点,本文尝试以 SQL 注入的角度探寻校验输入的重要性 以下实验均以 SQLI labs ...
- 「二」nginx下载与安装
1.下载地址(开源版):https://nginx.org/en/download.html wget https://nginx.org/download/nginx-1.14.2.tar.gz 2 ...
- springboot2.1.6整合activiti6.0(二)--网页流程编辑器bpmnjs
网页流程编辑器bpmnjs 官网:https://bpmn.io/ github:https://github.com/bpmn-io/bpmn-js-examples 因为还需要做一些改造,才能使其 ...
- Redis主从、哨兵
之前安装了redis,但是单节点redis不可靠,现在搭建redis主从,提高可用性. 一.搭建一主二从 redis主从其实是读写分离,主节点写数据,从节点读数据. 1.准备三台redis机器.red ...
- python 二级 标准库
1.turtle 函数 包括窗体函数.画笔状态.画笔运动函数 random库 3.time 时间处理.时间格式化.时间计时
- tsconfig.json 报错问题解决
tsconfig.json 报错问题解决 报错如图所示: 创建tsconfig.json配置文件时,VSCode会自动检测当前项目当中是否有ts文件,若没有则报错,提示用户需要创建一个ts文件后,再去 ...
- Go是怎么解决包依赖管理问题的?
我们先来了解一下 Go 构建模式的演化过程,弄清楚 Go 核心开发团队为什么要引入 Go module 构建模式. Go 构建模式时怎么演化的? Go 程序由 Go 包组合而成的,Go 程序的构建过程 ...