妙妙线段树+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 ...
随机推荐
- Ubuntu 部署饥荒联机版服务器 Linux DST_Dedicate_Server
0. 文件夹 - ~ |- ~/steamcmd # 装的是steamcmd_linux.tar.gz以及其解压出来的东西 |- ~/DST # 装的是DST服务器可执行文件.世界存档.世界模板 |- ...
- 腾讯解禁 QQ 极速版,且看我收集的最全 QQ 各类版本
因为利益关系,腾讯早就限制QQ极速版的登录了,近日居然解除限制了,面对越来越臃肿的QQ,我给大伙准备了几十个版本的QQ,总有一个适合你. QQ版本合集 给大伙们收集了QQ版本合集,分别有历史版本.精简 ...
- 如何在 CentOS 7 linux上安装和使用 FFmpeg
SSH首选FinalShell 1.下载解压 wget http://www.ffmpeg.org/releases/ffmpeg-5.1.tar.gz tar -zxvf ffmpeg-5.1.ta ...
- Elasticsearch搜索引擎学习笔记(三)
索引的一些操作 集群健康 GET /_cluster/health 创建索引 PUT /index_test { "settings": { "index": ...
- IOS 内付 asp.net mvc 服务器端验证
上代码: public class AppStorePayApp { public int VerifyReceipt(string receipt, out string product_id, o ...
- 【高德地图】离线地图jsapi2.0 插件引用
当引用一个插件,但是这个插件没有时会报错: Uncaught TypeError: AMap.ControlBar is not a constructor 这里引用了罗盘这个插件 这时候需要翻看高德 ...
- Linux权限与特殊权限
目录 5.1 权限讲解 5.1.1 什么是权限 5.1.2 为什么要管理权限 5.1.3 权限的分类 5.1.4 Linux的文件属于谁? 5.1.5 文件属主.属组.其他用户 5.1.6 所属者的表 ...
- 队列的实现方式(先进先出 FIFO)--环形队列
博客地址:https://www.cnblogs.com/zylyehuo/ # -*- coding: utf-8 -*- class Queue: def __init__(self, size= ...
- 在Proxmox VE pve中安装windows操作系统——以ltsc2019为例
pve创建ltsc2019还是比较简单的.只是没有virtio驱动的话,选择磁盘的时候找不到磁盘.这里主要是列出如何加载virtio驱动 1.创建虚拟机忽略.注意需要新建2个CDROM.一个为wind ...
- 接口介绍以及定义和使用--java进阶day02
1.接口介绍 日常生活中有很多接口,比如手机数据线的接口和手机充电器的接口 我们转换视角,站在设计者的角度思考接口,接口体现出规则,手机的接口大小和数据线的接口大小必须一致,各种接口的大小都要一致,都 ...