能够解决的题目类型

这个 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. CubeIDE 主题美化与颜色设置

    一.主题美化 搜索引擎里很多,这里不必多说. 二.颜色设置 2.1.关于控制台 菜单栏里:window→preference→输入"console"并回车,然后按照下图指示来: 2 ...

  2. Python爬虫之数据解析

    1.Request库 HTTP测试工具:http://httpbin.org,以下的示例会以此为URL 属于第三方库,需要手动安装 pip install requests 基本用法 import r ...

  3. IPC-7093A-CN 中文 2020底部端子元器件(BTCs)设计和组装工艺的实施

    IPC-7093A 标准为实施底部端子元器件(BTCs)提供了基本的设计和组装指南.具体而言,IPC-7093A 提供了与 BTCs 相关的关键设计.材料.组装.检查.维修.质量和可靠性问题的指南. ...

  4. Python之pandas读取Excel

    #! -*- coding utf-8 -*- """ 模块功能:读取当前文件夹下的Source里的Excel文件,显示其相关信息 说明:默认把Excel的第一行当做列名 ...

  5. JavaScript ES6基础

    1.let声明 1.let不像var有变量声明提升,未声明直接使用会报错 console.log(a); //undefined var a; console.log(b); //报错 let b; ...

  6. Fiddler模拟网络超时

    前情 最近在优化接口请求错误的报错提示,希望尽可能的能从提示语知道当前错误大致原因,于是我需要模拟各种错误请求的状况. 问题 网络超时是很常见的接口请求错误情况,在没有服务端配合的情况下,我需要怎样来 ...

  7. .NET 8 中的 ASP.NET Core 指标与 Grafana 仪表板入门

    .NET 8 中的 ASP.NET Core 指标与 Grafana 仪表板入门 原文地址:https://devblogs.microsoft.com/dotnet/introducing-aspn ...

  8. bytecode 生成器

    基础 objectweb asm 很难用,找了几个高级点的. activej codegen 这个库很像 .net DLR 风格,采用 Expression 抽象,例如 Expressions.add ...

  9. 一个.NET开源、易于使用的屏幕录制工具

    前言 一款高效.易用的屏幕录制工具能够极大地提升我们的工作效率和用户体验,今天大姚给大家分享一个.NET开源.免费.易于使用的屏幕录制工具:Captura. 工具介绍 Captura是一款基于.NET ...

  10. 自用Idea内存配置

    自用Idea内存配置 如下: 使用了zgc,自用48g内存的mac.可以应对8后端4前端同时使用. -Xms1g -Xmx12g -XX:+UseLargePages -XstartOnFirstTh ...