能够解决的题目类型

这个 Trick 能解决的题目形如:

  • 给定 \(n\) 个节点的有根无边权有点权树。
  • 有 \(m\) 个询问,每个询问形如点 \(x\) 的子树内与 \(x\) 深度差不超过 \(k\) 的点的极值/排名/和。
  • \(O(n\,log\,n)\) 可过。

优缺点

优点:可以强制在线,代码简单。

缺点:可能被卡常(概率非常小)。

思路

首先,深度差不超过 \(k\) 这个限制很难办,我们无法用一维的编号把这些点串起来,而且没有什么差分方法。

那么——二维,启动!

我们把一个数点 \(x\) 变成二维平面上的点:\((depp_x\,,dfn_x)\)。

那么对于一个点 \(p\) 的询问就变成了横坐标在 \([depp_p\,,depp_p+k]\) 中,纵坐标在 \([dfn_p\,,dfn_p+sz_p-1]\) 的点的极值/排名/和。

这个显然可以用树套树,但是 \(O(n\,log^2\,n)\),有没有更优的方法呢?

我们考虑主席树,但是主席树必须满足可减性,而最值没有。

但是,当一个点的横坐标在属于 \([1,depp_p-1]\) 时,他的纵坐标一定不属于 \([depp_p\,,dep_p+k]\),也就是说我们并不需要将两颗线段树相减,那么询问也就不用讲满足可减性。

所以我们就可以愉快地切题了。

算法流程

  1. 用一个 dfs 求出每个节点的 \(dfn,sz,depp\)。
  2. 把节点按照深度排序,一个一个加入主席树,并记录对于每个深度的最后一课主席树的根的下标 \(idx\)。

例题代码

本 Trick 的代码基本每道题没什么变化,直接套用就行了

CF893F Subtree Minimum Query

#include <bits/stdc++.h>
using namespace std; #define midd ((node[u].l + node[u].r) >> 1)
constexpr int maxn = 100010; int n, r, m, v[maxn], a, b, dfn[maxn], nowdfn, depp[maxn], s[maxn], idx[maxn], sz[maxn], lans, maxdep = 0;
vector <int> G[maxn]; struct nodee {
int v, l, r, ls, rs;
} ;
struct tr {
nodee node[maxn << 5];
int root[maxn], cnt;
void build(int &u, int l, int r) {
u = ++cnt;
node[u] = {1000000000, l, r, 0, 0};
if (l == r) return ;
build(node[u].ls, l, midd);
build(node[u].rs, midd + 1, r);
return ;
}
void update(int &u, int pree, int x, int k) {
u = ++cnt;
node[u] = node[pree];
node[u].v = min(node[u].v, k);
if (node[u].l == node[u].r) return ;
if (x <= midd) update(node[u].ls, node[pree].ls, x, k);
else update(node[u].rs, node[pree].rs, x, k);
return ;
}
int query(int u, int l, int r) {
if (node[u].l >= l && node[u].r <= r) return node[u].v;
int ress = 1000000000;
if (l <= midd) ress = min(query(node[u].ls, l, r), ress);
if (r > midd) ress = min(query(node[u].rs, l, r), ress);
return ress;
}
} t; void dfs(int u, int fa) {
sz[u] = 1;
dfn[u] = ++nowdfn;
for (int now : G[u]) {
if (now == fa) continue;
depp[now] = depp[u] + 1;
maxdep = max(maxdep, depp[now]);
dfs(now, u);
sz[u] += sz[now];
}
return ;
} signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); cin >> n >> r;
depp[r] = 1;
for (int i = 1; i <= n; i++) {
s[i] = i;
cin >> v[i];
}
for (int i = 1; i < n; i++) {
cin >> a >> b;
G[a].push_back(b);
G[b].push_back(a);
}
dfs(r, 0);
sort(s + 1, s + 1 + n, [](int a, int b){return depp[a] < depp[b];});
// 以上为第一部分 dfs
t.build(t.root[0], 1, n);
idx[0] = t.root[0];
for (int i = 1; i <= n; i++) {
t.update(t.root[i], t.root[i - 1], dfn[s[i]], v[s[i]]);
if (depp[s[i]] != depp[s[i + 1]]) idx[depp[s[i]]] = i;
}
// 以上为第二部分 主席树预处理
cin >> m;
while (m--) {
cin >> a >> b;
a = (a + lans) % n + 1;
b = (b + lans) % n;
lans = t.query(t.root[idx[min(maxdep, depp[a] + b)]], dfn[a], dfn[a] + sz[a] - 1);
cout << lans << '\n';
} return 0;
}

数据结构 Trick 之:子树 k 距离内问题的更多相关文章

  1. 【LeetCode】358.K 距离间隔重排字符串

    358.K 距离间隔重排字符串 知识点:哈希表:贪心:堆:队列 题目描述 给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少 ...

  2. OpenJudge数据结构与算法-计算点的距离并排序

    /*================================================================== 距离排序 总时间限制: 1000ms 内存限制: 65536k ...

  3. 排序算法 以及HKU的一些数据结构 相关题目 以及 K叉树,二叉树 排列

    冒泡排序.选择排序.快速排序.插入排序.希尔排序.归并排序.基数排序以及堆排序,桶排序 https://www.cnblogs.com/Glory-D/p/7884525.html https://b ...

  4. [Leetcode 787]中转K站内最便宜机票

    题目 n个城市,想求从src到dist的最廉价机票 有中转站数K的限制,即如果k=5,中转10次机票1000,中转5次机票2000,最后返回2000 There are n cities connec ...

  5. Laravel 框架根据经纬度计算在一定距离内的数据

    $model = DB::table('table_name'); public static function scope_distance($model, $from_latitude, $fro ...

  6. HDU 4347 - The Closest M Points - [KDTree模板题]

    本文参考: https://www.cnblogs.com/GerynOhenz/p/8727415.html kuangbin的ACM模板(新) 题目链接:http://acm.hdu.edu.cn ...

  7. LA3902 Network

    给出一棵树,对于每一个叶子节点要使得在它的k距离内至少一个节点被打了标记,(叶节点不能打标记,非叶结点也不必满足这个条件),现在已经有一个节点s被打了标记,问至少还要打几个标记(这表达能力也是捉急.. ...

  8. Leetcode——863.二叉树中所有距离为 K 的结点

    给定一个二叉树(具有根结点 root), 一个目标结点 target ,和一个整数值 K . 返回到目标结点 target 距离为 K 的所有结点的值的列表. 答案可以以任何顺序返回. 示例 1: 输 ...

  9. php mysql 计算经纬之间距离 范围内筛选

    <?php /** * 根据经纬度和半径计算出范围 * @param string $lat 纬度 * @param String $lng 经度 * @param float $radius ...

  10. 常用查找数据结构及算法(Python实现)

    目录 一.基本概念 二.无序表查找 三.有序表查找 3.1 二分查找(Binary Search) 3.2 插值查找 3.3 斐波那契查找 四.线性索引查找 4.1 稠密索引 4.2 分块索引 4.3 ...

随机推荐

  1. 1000%增长!我仅用一个小时搞定!AI智能体+AI小程序=MVP王炸组合!

    前言 在万圣节的前一晚上10月30日,一位运营朋友跟我说了个点子万圣节头像生成器,然后大概给我分析了下整体思路,于是我用扣子Coze平台(coze.cn)搭建了一个AI智能体整个过程花了一个小时就搞定 ...

  2. Mongodb的配置与登录

    1.下载完mongo后,把mongo的路径加入到用户与电脑的环境变量里面,如下图第二行. 2.新建一个文件夹,下面有db和log,两个文件夹,log里面新建一个mongodb.log文件,分别存放数据 ...

  3. NewStar CTF 2024 Crypto

    Week1 xor #As a freshman starting in 2024, you should know something about XOR, so this task is for ...

  4. typescript 安装调试(二)

    一.安装ts-node 今天介绍另外一种更加方便的ts调试方式,需要安装以下几个库 第一个库是ts-node,这个库可以直接运行ts文件无需实时编译成js文件后再运行 安装命令  npm i ts-n ...

  5. TIKZ——LaTeX基本绘图

    TIKZ是LaTeX的一个绘图包,可以绘制其他软件很难画出来的图像. 基本用法 直线.垂足.矩形.椭圆 代码: \documentclass{article} \usepackage{tikz} \u ...

  6. 成为JavaGC专家Part II — 如何监控Java垃圾回收机制

    本文是成为Java GC专家系列文章的第二篇.在第一篇<深入浅出Java垃圾回收机制>中我们学习了不同GC算法的执行过程,GC是如何工作的,什么是新生代和老年代,你应该了解的JDK7中的5 ...

  7. Contrastive Learning 对比学习 | RL 学 representation 时的对比学习

    记录一下读的三篇相关文章. 01. Representation Learning with Contrastive Predictive Coding arxiv:https://arxiv.org ...

  8. Linux之buffer/cache

    buffers和cached解释 =========================================================缓存(cached)是把读取过的数据保存起来,重新读 ...

  9. 正也科技S2P 数字化推动医药信息传播多元化

    在当今数字化迅猛发展的时代浪潮中,医药信息传播正经历着深刻而广泛的变革.这种变革犹如一场波澜壮阔的革命,席卷了医药领域的每一个角落,对医药行业的发展产生了深远且不可忽视的影响. 一.传播渠道的多元化拓 ...

  10. 禁用SAP Hana错误密码锁定用户功能

    背景 公司项目适配多种数据库其中包含SAP Hana,由于有同事的数据库连接工具保存了某个在用的数据库的旧密码,导致时不时会被锁用户.通过查询官方文档已解决,这里统一记录一下. 禁用密码锁定方法 以下 ...