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)的更多相关文章

  1. Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

    题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB    总提交次数:196   AC次数:65   平均分: ...

  2. Codeforces 343D WaterTree - 线段树, DFS序

    Description Translated by @Nishikino_Maki from Luogu 行吧是我翻的 Mad scientist Mike has constructed a roo ...

  3. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

  4. 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序

    题目大意 ​ Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...

  5. 【bzoj4817】树点涂色 LCT+线段树+dfs序

    Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...

  6. S - Query on a tree HDU - 3804 线段树+dfs序

    S - Query on a tree HDU - 3804   离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...

  7. 瞎写的树dfs序

    这里枚举了树的DFS序来解决树上问题的多个板子,自己最好多看看. ↓改↓ ↓求↓ 点 点 ————————>>>这个就算了 点 树 简单, BIT 点 链 重点! 树 树 简单, 线 ...

  8. 51 nod 1681 公共祖先 (主席树+dfs序)

    1681 公共祖先 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题   有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另 ...

  9. 【BZOJ】3991: [SDOI2015]寻宝游戏 虚树+DFS序+set

    [题意]给定n个点的带边权树,对于树上存在的若干特殊点,要求任选一个点开始将所有特殊点走遍后返回.现在初始没有特殊点,m次操作每次增加或减少一个特殊点,求每次操作后的总代价.n,m<=10^5. ...

  10. 【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 ...

随机推荐

  1. 2分钟学会 DeepSeek API,竟然比官方更好用!

    大家好,我是程序员鱼皮.最近 DeepSeek AI 太火了,效果也很强,但致命问题是 不稳定, 经常给我返回 服务器繁忙,请稍后再试,甚至让我怀疑自己被杀熟了. 也有网友说,第一次使用成功率很高,第 ...

  2. 8-2 MySQL 索引的设计原则(超详细说明讲解)

    8-2 MySQL 索引的设计原则(超详细说明讲解) @ 目录 8-2 MySQL 索引的设计原则(超详细说明讲解) 1. 测试数据准备 2. 哪些情况适合创建索引 2.1 字段的数值有唯一性的限制 ...

  3. ruoyi-vue axios通过接口请求wav、mp3音频二进制数据

    实现方式 在axios请求中注明responseType: 'blob',headers的Accept: 'audio/wav'不清楚要不要写,我加上了(请求接口) 在接口返回值中,使用Blob的构造 ...

  4. Qt QFileSystemModel 的使用

    Model 指的是数据 View 指的是界面,View不用设置,只需要和Model进行绑定,绑定完成之后就是Model的格式了 例子:本例子中QListView QTableView QTreeVie ...

  5. 如何让N1盒子、机顶盒开机从优盘启动进入刷机流程

    疑难解答加微信机器人,给它发:进群,会拉你进入八米交流群 机器人微信号:bamibot 简洁版教程访问:https://bbs.8miyun.cn 准备阶段 1.下载我的从优盘启动的工具包 2.确认你 ...

  6. springboot+vue项目:工具箱

    常用账号管理:工作相关账号.游戏账号.各平台账号 加班调休管理:公司没有对应的系统,需要自己记录加班调休情况. 待办事项:方便记录待办,以提醒还有哪些事情没有办理. 待实现功能: 1.点击侧边栏菜单, ...

  7. 华为平板+Zotero+Xodo+坚果云+Zotfile+Zotero OCR,实现论文笔记平板手写+Win自动生成,补充官方教程

    需要的硬件,软件,插件和实现的最终效果,rt. 1. Win,下载Zotero,坚果云 下载网址:https://www.zotero.org/download/ 版本:Zotero 6.如果是其他版 ...

  8. Linux权限与特殊权限

    目录 5.1 权限讲解 5.1.1 什么是权限 5.1.2 为什么要管理权限 5.1.3 权限的分类 5.1.4 Linux的文件属于谁? 5.1.5 文件属主.属组.其他用户 5.1.6 所属者的表 ...

  9. PX4 仿真环境开发整理

    博客地址:https://www.cnblogs.com/zylyehuo/ (一)PX4 仿真开发 搭建仿真环境 概念介绍及环境建议 MAVROS安装(适用于ROS1.ROS2) Ubuntu安装Q ...

  10. 小白必看的cmd简单代码!(图片看不到的可复制 粘贴到Typroa进行观看)

    打卡cmd的方法 直接window加r 输入cmd 在下方菜单 找到window标志,打开 输入命令提示符 更高级的cmd权限使用:右键命令提示符,点击"以管理员身份运行" 一些简 ...