• 【蓝桥】小蓝的疑问


    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    样例输出

    8
    9
    8
    7
    
    • 1
    • 2
    • 3
    • 4

    说明

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

    数据范围

    • 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 
    #include 
    #include 
    #include 
    #include 
    #include 
    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 面向对象
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
  • 相关阅读:
    期末复习 c
    (5)打印nXn方阵
    【Unity】【VR】如何用键鼠模拟VR输入
    运筹系列77:开源线性规划软件clp使用简介
    【Shell编程】字符截取命令awk、sed命令
    独热编码和自然数编码
    MySQL存储引擎
    RK3588芯片介绍
    Git 入门实用命令
    在Ubuntu中创建Ruby on Rails项目并搭建数据库
  • 原文地址:https://blog.csdn.net/u011386173/article/details/134021268