最短线段树

最短线段树是一种优化的数据结构,用于快速查找区间内的最小值及其位置。它基于线段树的原理,每个节点存储区间的最小值和对应的索引。文章提供了C++实现代码,包括构建、查询和更新操作,展示了如何在实际问题中应用最短线段树。
摘要由CSDN通过智能技术生成

线段树(Segment Tree)是一种常见的数据结构,用于解决区间查询问题。最短线段树(Shortest Segment Tree)是线段树的一种变种,用于快速查询一个区间的最小值及其位置。本文将详细介绍最短线段树的原理、实现方法和应用场景。

一、原理

最短线段树的原理和普通线段树的原理类似,都是通过递归的方式将区间划分为更小的区间,然后在每个节点上维护一些信息。最短线段树在每个节点上维护区间的最小值和最小值的位置。当查询某个区间的最小值时,除了返回区间最小值,还可以返回该最小值在区间中的位置。

下面是最短线段树的一般实现流程:

  1. 将区间划分为更小的区间,直到每个区间只有一个元素。

  2. 在每个节点上维护该区间的最小值和最小值的位置。

  3. 查询某个区间的最小值及其位置时,从根节点开始向下递归,如果该节点所表示的区间完全包含查询区间,则直接返回该节点的最小值和最小值的位置;否则,分别递归左子树和右子树,然后合并两个子树的结果,返回合并后的最小值和最小值的位置。

  4. 修改某个位置的值时,从根节点开始向下递归,找到包含该位置的节点,更新该节点的最小值和最小值的位置,并继续向下递归,直到叶子节点。

二、实现

下面是最短线段树的具体实现代码(使用 C++ 实现):

#include <iostream>
#include <climits>
#include <algorithm>

using namespace std;

const int MAXN = 100000;

struct Node {
    int min_val, min_pos;
};

int n;
int a[MAXN];
Node tree[4*MAXN];

void build(int idx, int l, int r) {
    if (l == r) {
        tree[idx].min_val = a[l];
        tree[idx].min_pos = l;
    } else {
        int mid = (l+r)/2;
        build(2*idx, l, mid);
        build(2*idx+1, mid+1, r);
        if (tree[2*idx].min_val <= tree[2*idx+1].min_val) {
            tree[idx].min_val = tree[2*idx].min_val;
            tree[idx].min_pos = tree[2*idx].min_pos;
        } else {
            tree[idx].min_val = tree[2*idx+1].min_val;
            tree[idx].min_pos = tree[2*idx+1].min_pos;
        }
    }
}

Node query(int idx, int l, int r, int ql, int qr) {
    if (l > qr || r < ql) {
        return {INT_MAX, -1};
    }
    if (l >= ql && r <= qr) {
        return tree[idx];
    }
    int mid = (l+r)/2;
    Node left = query(2*idx, l, mid, ql, qr);
    Node right = query(2*idx+1, mid+1, r, ql, qr);
    if (left.min_val <= right.min_val) {
        return left;
    } else {
        return right;
    }
}

void update(int idx, int l, int r, int pos, int val) {
    if (l == r) {
        a[pos] = val;
        tree[idx].min_val = val;
        tree[idx].min_pos = pos;
    } else {
        int mid = (l+r)/2;
        if (pos <= mid) {
            update(2*idx, l, mid, pos, val);
        } else {
            update(2*idx+1, mid+1, r, pos, val);
        }
        if (tree[2*idx].min_val <= tree[2*idx+1].min_val) {
            tree[idx].min_val = tree[2*idx].min_val;
            tree[idx].min_pos = tree[2*idx].min_pos;
        } else {
            tree[idx].min_val = tree[2*idx+1].min_val;
            tree[idx].min_pos = tree[2*idx+1].min_pos;
        }
    }
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    build(1, 1, n);
    Node res = query(1, 1, n, 2, 4);
    cout << "Min value: " << res.min_val << ", min position: " << res.min_pos << endl;
    update(1, 1, n, 3, -1);
    res = query(1, 1, n, 2, 4);
    cout << "Min value: " << res.min_val << ", min position: " << res.min_pos << endl;
    return 0;
}
``

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dijkstra算法是一种用于解决单源最短路径问题的经典算法,它的时间复杂度为O(V^2),其中V是图中顶点的数量。通过使用线段树优化Dijkstra算法,可以将其时间复杂度降低到O((V+E)logV),其中E是图中边的数量。 下面是使用线段树优化Dijkstra算法的一般步骤: 1. 创建一个大小为V的距离数组dist[],用于记录从源节点到每个节点的当前最短距离,初始时将所有距离初始化为无限大,源节点的距离初始化为0。 2. 创建一个大小为V的布尔数组visited[],用于记录每个节点是否已被访问过,初始时将所有节点标记为未访问。 3. 创建一个线段树,用于快速查询未访问节点中距离最小的节点。 4. 将源节点加入线段树,并将其距离设置为0。 5. 重复以下步骤,直到线段树为空: - 从线段树中选择距离最小的节点u,并将其从线段树中删除。 - 标记节点u为已访问。 - 遍历节点u的所有邻居节点v: - 如果节点v未被访问过且通过节点u到达节点v的距离更短,则更新节点v的距离为新的最短距离,并将节点v插入线段树中。 6. 最终,dist[]数组中存储的即为从源节点到每个节点的最短距离。 通过使用线段树优化Dijkstra算法,可以减少在每次查找最小距离节点时的时间复杂度,从而提高算法的效率。需要注意的是,在实现过程中,还需要根据具体问题进行相应的调整和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值