ACM_线段树

本文介绍了线段树这一数据结构,用于区间操作。通过示例展示了如何进行单点更新和区间查询,解释了线段树的基本结构和关键函数,包括push_up、build、update和query,帮助理解线段树如何高效地维护区间最大值。
摘要由CSDN通过智能技术生成

线段树:
自我理解:把一段区间整体操作的数据结构

整体思路:
这里写图片描述

如图:
假如单点更新 区间查询 现在有10个数
这10个数最开始是 1 2 3 4 5 6 7 8 9 10
查询某个区间的最大值
那么把这些区间按照如下更新
这里写图片描述

现在假如我们查询 2-7的最大值 (当然主观上我们明显知道是7)
我们就可以查询max[2, 2] = 2, max[3, 3] = 3, max[4, 5] = 5, max[6, 7] = 7, 取最大的 = 7;(为什么不直接查询[2, 7]呢, 因为线段树里没有这个区间)
所以我们就知道[2, 7]的最大值是7;

现在假如我们更新其中的一个值:
比如我们把5点的值更新成100;这里写图片描述
每个区间的最大值就成了这样

下次我们再查询max[2, 7]的时候:
max[2, 2] = 2, max[3, 3] = 3, max[4, 5] = 100, max[6, 7] = 7;
取最大的是100;
最大值就等于100;

基本结构:
每个区间都会有1个rt 代表该区间:
然后每个区间的基本结构有3个参数(l, r, rt)分别代表这个区间的左端点, 右端点, 区间的下标)
首先 整个区间的下标用1表示
每个区间的中点m = l + r >> 1;
然后每个父节点有一个左儿子:(l, m, rt << 1)一个右儿子(m+1, r, rt << 1 | 1)如此建树

几个函数:
void push_up(向上推)
void push_donw(向下推, 当然这个题不需要这个功能, 求区间和的时候需要)
void build(建树)
void update(更新某些值)
int query(查询符合要求的值)

  1. void push_up

    void push_up(int rt){
        h[rt] = max(h[rt << 1], h[rt << 1 | 1]);
    }

    h代表最大值 [l, r]的最大值等于它左儿子的最大值和右儿子的最大值里大的那个;

  2. build

    void build(int l, int r, int rt){
        if(l == r){
            scanf("%d", &h[rt]);
            return;
        }
        int m = l + r >> 1;
            build(lson);
            build(rson);
            push_up(rt);
        }

当不断向下搜索知道l = r的时候, 那么这个区间就只有1个值, 那么这个值一定就是最大值, 读入它;
否则 我们把它的左边儿子建立了, 右边儿子建立了, 再从它左儿子和右儿子两个最大值中取大的那个;

这里写图片描述

建树后就变成了上图, 其中黑色底字是区间, 红色的字是区间的最大值, 绿色的字是区间的下标

  1. void update

    void update(int x, int y, int l, int r, int rt){
        if(l == r){
            h[rt] = max(h[rt], y);
            return;
        }
        int m = l + r >> 1;
        if(x <= m) update(x, y, lson);
        else update(x, y, rson);
        push_up(rt);
    }

    如果l = r 说明该区间只有1个值了, 那么更新到这里把需要更新的值读入就OK了, 该值一定是最大值
    否则就继续向下更新 并在两个儿子的最大值中取最大的那个

    比如更新把5更新成100
    按照天蓝色的线更新:注意一下路上区间的最大值变化(红色的字)

这里写图片描述

  1. int query
int query(int L, int R, int l, int r, int rt){
    if(L <= l && r <= R) return h[rt];
    int ret = -INF;
    int m = l + r >> 1;
    if(L <= m) ret = max(ret, query(L, R, lson));
    if(R > m) ret = max(ret, query(L, R, rson));
    return ret;
}

查询函数: if(L <= l && r <= R)说明查询的区间已经包含到了向下询问的空间了, 直接返回这个区间的最大值就OK了
否则就返回它的左儿子和右儿子的最大值中较大的那个就OK了;
这里写图片描述
顺着天蓝色的线向下找, 找到这些区间的最大值并返回就OK

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的医院后台管理系统实现了病房管理、病例管理、处方管理、字典管理、公告信息管理、患者管理、药品管理、医生管理、预约医生管理、住院管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让医院后台管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值