【蓝桥】小蓝的疑问

news2024/9/23 1:40:23

1、题目

问题描述

小蓝和小桥上完课后,小桥回顾了课上教的树形数据结构,他在地上画了一棵根节点为 1 的树,并且对每个节点都赋上了一个权值 w i w_i wi

小蓝对小桥多次询问,每次询问包含两个整数 x , k x,k x,k,表示询问节点为 x x x 的所有 k k k 层子节点中,最大值是多少。

我们称节点 v v v x x x k k k 层子节点满足:

  1. v v v x x x 为根的子树中的节点。
  2. d e p v − d e p x = k dep_v - dep_x = k depvdepx=k d e p v dep_v depv v v v 在树中的深度。

例如:
在这里插入图片描述
{2, 3} 为 1 号点的 1 层子节点,{4, 5, 6, 7} 为 1 号点的 2 层子节点,{4, 6} 为 2 号点的 1 层子节点。

输入格式

第一行输入两个正整数 n , q n,q n,q,表示树的节点数量和询问数量。

第二行输入 n n n 个正整数 w 1 , w 2 , . . . , w n w_1, w_2, ..., w_n w1,w2,...,wn,表示每个点的权值。

接下来 n − 1 n-1 n1 行,每行输入两个整数 v i , u i v_i, u_i vi,ui,表示存在一条由 v i v_i vi 指向 u i u_i ui 的边。

接下来 q q q 行,每行输入两个整数 x , k x, k x,k,表示询问 x x x k k k 层子节点中,最大值是多少。

输出格式

输出 q q q 行,每行输出一个整数,表示每个询问的最大值。

样例输入

7 4
2 9 8 7 8 6 4
1 2
1 3
2 4
2 6
3 5
3 7
1 2
1 1
3 1
2 1

样例输出

8
9
8
7

说明

样例如下图:
在这里插入图片描述

数据范围

  • 1 ≤ v i , u i , k , x ≤ n ≤ 1 0 5 1 \le v_i, u_i, k, x \le n \le 10^5 1vi,ui,k,xn105
  • 1 ≤ w i ≤ 1 0 9 1 \le w_i \le 10^9 1wi109
  • 1 ≤ q ≤ 1 0 5 1 \le q \le 10^5 1q105
  • 数据保证是一棵以 1 为根的有向树,并且每次询问的 k k k 一定合法。

原题链接

小蓝的疑问

2、思路

考察数据结构(堆,线段树),图(DFS序),二分查找

  1. 离线做法:启发式合并 + 优先队列,同时对于每层的节点都维护一个大根堆,每次询问,查询堆中最大值。时间复杂度: O ( n l o g 2 n ) O(n log^2n) O(nlog2n)
  2. 在线做法:DFS序 + 线段树(ST表)+ 二分查找,对每层按照 DFS 序相对顺序建立线段树(或者 ST 表),当查询到 u u u 时,通过二分找到 k k k 层的左右端点,查询最大值。时间复杂度: O ( n l o g n ) O(n log n) O(nlogn)

在这里插入图片描述

3、代码

  • 强制合并
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <queue>
#include <assert.h>
using namespace std;

typedef long long ll;
const int N = 1e5 + 100;
const int MOD = 998244353;

vector<int> G[N];
int n, q;
int w[N];
int Siv[N], Son[N], ans[N];

typedef pair<int, int> Pair;

vector<Pair> query[N];

priority_queue<Pair> Dep[N];

int DFN = 0, rdn[N], dfn[N], dep[N];
int vis[N];

int ddep[N];

void dfs(int u, int fa = 0, int dpt = 1) {
    ddep[u] = dpt;
    Siv[u] = 1;

    for (int v : G[u]) {
        if (v == fa) continue;
        dfs(v, u, dpt + 1);
        ddep[u] = max(ddep[u], ddep[v]);
        Siv[u] += Siv[v];
        if (Siv[v] > Siv[Son[u]]) Son[u] = v;
    }
}

void to_get_ans(int u, int fa = 0, int dpt = 1, bool clr = false) {
    dfn[u] = ++DFN;
    rdn[dfn[u]] = u;
    dep[u] = dpt;
    for (int v : G[u]) {
        if (v == fa || v == Son[u]) continue;
        to_get_ans(v, u, dpt + 1, false);
    }

    if (Son[u]) {
        to_get_ans(Son[u], u, dpt + 1, true);
    }
    

    int ed = dfn[u];
    if (Son[u]) ed = dfn[Son[u]] - 1;

    for (int i = dfn[u]; i <= ed; ++i) {
        int vv = rdn[i];
        Dep[dep[vv]].push({w[vv], vv});
        vis[vv] = true;
    }
    // cout << endl;

    for (Pair q : query[u]) {
        int k = q.first;
        assert(k + dpt <= ddep[u]);
        int id = q.second;
        while (Dep[k + dpt].size() && vis[Dep[k + dpt].top().second] == 0) {
            Dep[k + dpt].pop();
            
        }
        ans[id] = Dep[k + dpt].top().first;
    }

    if (!clr) {
        int ed = dfn[u] + Siv[u];
        for (int i = dfn[u]; i < ed; ++i) {
            vis[rdn[i]] = false;
        }
    }

}

void sol() {
    cin >> n >> q;
    for (int i = 1; i <= n; ++i) {
        cin >> w[i];
    }   
    int u, v; 
    for (int i = 1; i < n; ++i) {
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1);
    int x, k;
    for (int i = 1; i <= q; ++i) {
        cin >> x >> k;
        query[x].push_back({k, i});
    }
    to_get_ans(1);
    for (int i = 1; i <= q; ++i) {
        cout << ans[i] << '\n';
    }
}

int main() {
    int T = 1;
    while (T--) {
        sol();
    }
    exit(0);
}
  • 面向对象
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <queue>
#include <assert.h>
#include <cmath>

using namespace std;

typedef long long ll;
const int N = 1e5 + 100;

vector<int> G[N], val[N], dfsQ[N];
int w[N], n, q;
int DFN = 0, dfn[N], dep[N], Siv[N], MaxDpt = 0;

class RMQ_t {
public:
    RMQ_t(const vector<int>& init);
    ~RMQ_t();
    int query(int l, int r) const {
        int k = log2(r - l);
        return max(f[k][l], f[k][r - (1 << k)]);
    }
private:
    int **f;
    const int N, LOGN;
};

RMQ_t *res[N];

void dfs(int u, int fa = 0, int dpt = 1) {
    MaxDpt = max(MaxDpt, dpt);
    dfn[u] = ++DFN; dep[u] = dpt;
    Siv[u] = 1;
    val[dpt].push_back(w[u]);
    dfsQ[dpt].push_back(dfn[u]);
    for (int v : G[u]) {
        if (v == fa) continue;
        dfs(v, u, dpt + 1);
        Siv[u] += Siv[v];
    }
}

void sol() {
    cin >> n >> q;
    for (int i = 1; i <= n; ++i) {
        cin >> w[i];
    }   
    int u, v, x, k; 
    for (int i = 1; i < n; ++i) {
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1);
    for (int i = 1; i <= MaxDpt; ++i) {
        res[i] = new RMQ_t(val[i]);
    }
    while (q--) {
        cin >> x >> k;
        int l = lower_bound(dfsQ[k + dep[x]].begin(),
                            dfsQ[k + dep[x]].end(),
                            dfn[x]) - dfsQ[k + dep[x]].begin();
        int r = lower_bound(dfsQ[k + dep[x]].begin(),
                            dfsQ[k + dep[x]].end(),
                            dfn[x] + Siv[x]) - dfsQ[k + dep[x]].begin();
        cout << res[k + dep[x]]->query(l,r) << endl;
    }
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
    int T = 1;
    while (T--) {
        sol();
    }
    exit(0);
}

RMQ_t::RMQ_t(const vector<int>& init) : N(init.size()), LOGN(log2(init.size()) + 1) {
    f = new int*[LOGN];
    for (int i = 0; i < LOGN; ++i) {
        f[i] = new int[N];
    }
    for (int i = 0; i < N; ++i) {
        f[0][i] = init[i];
    }
    for (int i = 1; i < LOGN; ++i) {
        for (int j = 0; j + (1 << i) - 1 < N; ++j) {
            f[i][j] = max(f[i - 1][j], f[i - 1][j + (1 << (i - 1))]);
        }
    }
}

RMQ_t::~RMQ_t() {
    for (int i = 0; i < LOGN; ++i) {
        delete[] f[i];
    }
    delete[] f;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1134790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Iterator迭代器

一、基本概念 Iterator迭代器是一种接口&#xff0c;为不同的数据结构提供一种访问机制&#xff0c;即for … of 循环。当使用for…of循环遍历某种数据结构时&#xff0c;该循环会自动去寻找 Iterator 接口。任何数据结构只要部署Iterator接口&#xff0c;就可以完成遍历操作(…

基于Pytorch的驾驶员分心行为实时检测

本文使用深度学习和Pytorch(PyTorch 2.0.1\Torchvision 0.15.2)实时检测驾驶员的分心行为,并附录完整代码。 检测分心驾驶是现代汽车中最重要的功能之一。无论是自动驾驶汽车还是其它高端汽车,都配备了驾驶员监控系统,以持续跟踪驾驶员的行为。这对确保驾驶员保持目光在道路…

Unity的碰撞检测(二)

温馨提示&#xff1a;本文基于前一篇“Unity的碰撞检测(一)”继续探讨Collider输出&#xff0c;阅读本文则默认已阅读前文。 &#xff08;一&#xff09;测试说明 对于Collider输出&#xff0c;我们首先应该保证两个游戏对象具备的是碰撞器而非触发器&#xff0c;所以碰撞器的…

LSTM算法精解(附案例代码)

概念 LSTM&#xff08;Long Short-Term Memory&#xff09;是一种循环神经网络&#xff08;RNN&#xff09;的变种&#xff0c;用于处理序列数据&#xff0c;特别是在需要长期依赖关系的情况下。LSTM旨在解决传统RNN存在的梯度消失和梯度爆炸问题&#xff0c;这些问题使得RNN难…

18 Transformer 的动态流程

博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from333.1007.0.0 b 站直接看 配套 github 链接&#xff1a;https://github.com/nickchen121/Pre-training-language-model 配套博客链接&#xff1a;https://www.cnblogs.com/nickchen121/p/15105048.html 机…

【BI看板】superset api接口分析

superset 的图表功能已经非常强大了&#xff0c;但是要满足个性化需求&#xff0c;定制是比不可少的了。。。来吧&#xff0c;我们一起看看他的API。 自带api文档 URL 127.0.0.1:5000/swagger/v1 截图 是不是很熟悉&#xff0c;没错就是swagger了。 图表接口地址 127.0.0.1:…

2698 求一个整数的惩罚数 (子集和,DFS)

class Solution { public:bool dfs(int target, string s, int index, int sum) {// 只有整个字符串都被分割&#xff0c;求和&#xff0c;和看结果是不是等于targetif(index s.size()) {return sum target;}int num 0; // 在现在的子集中去依次加入余下的元素// 1 2 9 6// …

vue3 code format bug

vue code format bug vue客户端代码格式化缺陷&#xff0c;为了方便阅读和维护&#xff0c;对代码格式化发现这个缺陷 vue.global.min.3.2.26.js var Vuefunction(r){"use strict";function e(e,t){const nObject.create(null);var re.split(",");for(le…

VLAN实现二层流量隔离(mux-vlan)应用基础配置

MUX VLAN能够提供VLAN内的二层流量隔离机制。 MUX VLAN的类型如下所示 主VLAN: 加入主VLAN的接口可以和MUX VLAN内的所有接口进行通信 从VLAN: (1)隔离型从VLAN: 同一VLAN内接口之间不能互相通信&#xff0c;可以与主VLAN接口通信&#xff0c;不同从VLAN之间不能互相通信。 …

Xcode iOS app启用文件共享

在info.plist中添加如下两个配置 Supports opening documents in place Application supports iTunes file sharing 结果都为YES&#xff0c;如下图所示&#xff1a; 然后&#xff0c;iOS设备查看&#xff0c;文件->我的iPhone列表中有一个和你工程名相同的文件夹出现&…

MySQL——MySQL常见的面试知识

1、事务四大特性 原子性&#xff1a; 根据定义&#xff0c;原子性是指一个事务是一个不可分割的工作单位&#xff0c;其中的操作要么都做&#xff0c;要么都不做。即要么转账成功&#xff0c;要么转账失败&#xff0c;是不存在中间的状态&#xff01;MySQL的InnoDB引擎是靠 un…

Mysql数据库 4.SQL语言 DQL数据操纵语言 查询

DQL数据查询语言 从数据表中提取满足特定条件的记录 1.单表查询 2.多表查询 查询基础语法 select 关键字后指定要查询到的记录的哪些列 语法&#xff1a;select 列名&#xff08;字段名&#xff09;/某几列/全部列 from 表名 [具体条件]&#xff1b; select colnumName…

UI设计公司成长日记2:修身及持之以恒不断学习是要务

作者&#xff1a;蓝蓝设计 要做一个好的UI设计公司,不仅要在能力上设计能力一直&#xff08;十几年几十年&#xff09;保持优秀稳定的保持输出&#xff0c;以及心态的平和宽广。创始人对做公司要有信心&#xff0c;合伙人之间要同甘共苦&#xff0c;遵守规则&#xff0c;做好表…

text-indent 的特殊性

目录 前言 1. text-indent 的基本用法 代码示例 理解 2. text-indent 的特殊性质 2.1 负值 代码示例 理解 2.2 与其他文本属性的交互 代码示例 理解 2.3 在不同元素上的表现 代码示例 理解 3. 如何正确使用 text-indent 前言 text-indent 是 CSS 中一个用来控制…

1401 位置编码公式详细理解补充

博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https://github.com/nickchen121/Pre-training-language-model 配套博客链接:https://www.cnblogs.com/nickchen121/p/15105048.html Self-Attention:对于每…

day01:数据库DDL

一:基础概念 数据库:存储数据的仓库&#xff0c;数据是有组织的进行存储 数据库管理系统:操纵和管理数据库的大型软件 SQL&#xff1a;操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库统一标准 关系图 二:数据模型 关系型数据库:建…

LSM树原理详解

LSM树(Log-Structured-Merge-Tree)的名字往往会给初识者一个错误的印象&#xff0c;事实上&#xff0c;LSM树并不像B树、红黑树一样是一颗严格的树状数据结构&#xff0c;它其实是一种存储结构&#xff0c;目前HBase,LevelDB,RocksDB这些NoSQL存储都是采用的LSM树。 LSM树的核…

基于Java的智能仓库(进销存)管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

USB学习(2):USB端点和传输协议(数据包、事物)详解

接着上一篇文章USB学习(1)&#xff1a;USB基础之接口类型、协议标准、引脚分布、架构、时序和数据格式&#xff0c;继续介绍一下USB的相关知识。 文章目录 1 USB端点(Endpoints)1.1 基本知识1.2 四种端点 2 传输协议2.1 数据包类型2.1.1 令牌数据包(Token packets)2.1.2 数据数…

目标检测应用场景—数据集【NO.16】交通标志检测

写在前面&#xff1a;数据集对应应用场景&#xff0c;不同的应用场景有不同的检测难点以及对应改进方法&#xff0c;本系列整理汇总领域内的数据集&#xff0c;方便大家下载数据集&#xff0c;若无法下载可关注后私信领取。关注免费领取整理好的数据集资料&#xff01;今天分享…