树和树结构(4): 线段树(部分转载)

原文来自http://blog.csdn.net/metalseed/article/details/8039326, 有改动
使用tyvj1039_忠诚2 作为测试题目: http://www.tyvj.cn/p/1039
源码下载 Tyvj1039_忠诚2.cpp

一:线段树基本概念
0: 图片

1:概述
线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(lgN)!
性质:父亲的区间是[a,b],(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b],线段树需要的空间为数组大小的四倍
个人感觉: 其实是将区间二分, 预处理出一部分区间值. 这样在查询某一个区间最小值时, 可以直接调用其中一部分. 例如在1..10的区间内求2..6的最小值, 实质上可以变为求2..(1+10)/2最小值和(1+10)/2+1..6的最小值. 前者又可以划分为2..3和4..5等等等, 以此类推. 读者可以用手算下1..100区间内求31..78的最小值过程, 可以理解线段树高效的原因.

首先建立线段树的数据结构:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define INF 100000001
    #define half(x) ((x)>>(1))
    using namespace std;

    int nums[100005];
    int n, q;

    typedef struct node;
    typedef node *tree;
    int init(tree &t, int from, int to);
    struct node {
    tree lc, rc;
        //左右子树
        int left, right, value;
        //线段
        node() {
                lc = rc = NULL;
                left = right = value = 0;
        }
    }*root;

2:基本操作(demo用的是查询区间最小值)
线段树的主要操作有:
(1):线段树的构造 void init(node, begin, end);
主要思想是递归构造,如果当前节点记录的区间只有一个值,则直接赋值,否则递归构造左右子树,最后回溯的时候给当前节点赋值
注意: 为了节约空间, 这里给出的代码只将区间划分为i..i+1.

    int init(tree &t, int from, int to)
    {
        if (to < from) return INF;
        if (from == to) return nums[from];
        //到达边界
        if (t == NULL)
            t = new node;
        t->left = from;    
        t->right = to;
        return t->value = min(
        init(t->lc, from, half(from+to)),
        init(t->rc, half(from+to)+1, to)
        );
        //递归构建左右子树
    }

(2):区间查询int ask_min(tree n, int from, int to)
(其中n为当前查询节点,from, to为此次query所要查询的区间)
主要思想是把所要查询的区间[a,b]划分为线段树上的节点,然后将这些节点代表的区间合并起来得到所需信息
比如前面一个图中所示的树,如果询问区间是[0,2],或者询问的区间是[3,3],不难直接找到对应的节点回答这一问题。但并不是所有的提问都这么容易回答.

询问有且只有五种情况:
0 线段长度为0
1 和此节点重合
2 被此节点的左子树包含
3 被此节点的右子树包含
4 可分成左右两部分

据此很容易写出子程序

    int ask_min(tree n, int from, int to)
    {
        if (from == to) return nums[from];           //0
        if (to < from || !n || (n->left > from && n->right < to)) return INF;
        //剪去无意义的
        if (n->left == from && n->right == to)
            return n->value;                     //1
        if (n->left <= from && half(n->left+n->right) >= to)
            return ask_min(n->lc, from, to);     //2
        if (half(n->left+n->right)+1 <= from && n->right >= to)
            return ask_min(n->rc, from, to);     //3
        return min(
        ask_min(n->lc, from, half(n->left+n->right)),
        ask_min(n->rc, half(n->left+n->right)+1, to)
        );                                           //4
    }

(3):节点的更新 动态维护void update(tree &n, int num)
由顶自下更新, 再返回来向上更新. 先写一个获取此节点值的函数:

    int value(tree n) {
        if (!n->lc)
            return min(nums[n->left], nums[n->right]);
        //左子树为空, 说明左右都为空
        if (!n->rc)
            return min(n->lc->value, nums[n->right]);
        //右子树为空, 左子树不为空
        return min(n->lc->value, n->rc->value);
        //都不为空
    }

再写更新(这个需要好好理解递归构树):

    void update(tree &n, int num)
    {
        if (!n)
            return; //到底部了
        if (num <= half(n->left+n->right)) {
            update(n->lc, num);
            n->value = value(n);
            //向左子树更新
        } else {
            update(n->rc, num);
            n->value = value(n);
            //向右子树更新
        }
    }

最后呼之欲出的main!

    int main()
    {
        scanf ("%d%d", &n, &q);
        for (int i=1; i<=n; i++)
            scanf ("%d", &nums[i]);
        init(root, 1, n);
        for (int i=1; i<=q; i++) {
            int order, f, t;
            scanf ("%d%d%d", &order, &f, &t);
            if (order == 1)
                printf ("%d ", ask_min(root,f,t));
            if (order == 2) {
                nums[f] = t;
                update (root, f);
            }
        }
        return 0;
    }

通过这个练习, 对树结构有了更深刻的理解. 十分欣赏树结构的简洁, 美观, 高效!

明天就要期中考了, 还是忍不住来发个文. 对原文做了一些NOIp难度的改动, 希望对大家有些帮助.
发技术文好累23333

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园信息化系统解决方案旨在通过先进的信息技术,实现教育的全方位创新和优质资源的普及共享。该方案依据国家和地方政策背景,如教育部《教育信息化“十三五”规划》和《教育信息化十年发展规划》,以信息技术的革命性影响为指导,推进教育信息化建设,实现教育思想和方法的创新。 技术发展为智慧校园建设提供了强有力的支撑。方案涵盖了互连互通、优质资源共享、宽带网络、移动APP、电子书包、电子教学白板、3D打印、VR虚拟教学等技术应用,以及大数据和云计算技术,提升了教学数据记录和分析水平。此外,教育资源公共服务平台、教育管理公共服务平台等平台建设,进一步提高了教学、管控的效率。 智慧校园系统由智慧教学、智慧管控和智慧办公三大部分组成,各自具有丰富的应用场景。智慧教学包括微课、公开课、精品课等教学资源的整合和共享,支持在线编辑、录播资源、教学分析等功能。智慧管控则通过平安校园、可视对讲、紧急求助、视频监控等手段,保障校园安全。智慧办公则利用远程视讯、无纸化会议、数字会议等技术,提高行政效率和会议质量。 教育录播系统作为智慧校园的重要组成部分,提供了一套满足学校和教育局需求的解决方案。它包括标准课室、微格课室、精品课室等,通过自动五机位方案、高保真音频采集、一键式录课等功能,实现了优质教学资源的录制和共享。此外,录播系统还包括互动教学、录播班班通、教育中控、校园广播等应用,促进了教育资源的均衡化发展。 智慧办公的另一重点是无纸化会议和数字会议系统的建设,它们通过高效的文件管理、会议文件保密处理、本地会议的音频传输和摄像跟踪等功能,实现了会议的高效化和集中管控。这些系统不仅提高了会议的效率和质量,还通过一键管控、无线管控等设计,简化了操作流程,使得会议更加便捷和环保。 总之,智慧校园信息化系统解决方案通过整合先进的信息技术和教学资源,不仅提升了教育质量和管理效率,还为实现教育均衡化和资源共享提供了有力支持,推动了教育现代化的进程。
智慧校园信息化系统解决方案旨在通过先进的信息技术,实现教育的全方位创新和优质资源的普及共享。该方案依据国家和地方政策背景,如教育部《教育信息化“十三五”规划》和《教育信息化十年发展规划》,以信息技术的革命性影响为指导,推进教育信息化建设,实现教育思想和方法的创新。 技术发展为智慧校园建设提供了强有力的支撑。方案涵盖了互连互通、优质资源共享、宽带网络、移动APP、电子书包、电子教学白板、3D打印、VR虚拟教学等技术应用,以及大数据和云计算技术,提升了教学数据记录和分析水平。此外,教育资源公共服务平台、教育管理公共服务平台等平台建设,进一步提高了教学、管控的效率。 智慧校园系统由智慧教学、智慧管控和智慧办公三大部分组成,各自具有丰富的应用场景。智慧教学包括微课、公开课、精品课等教学资源的整合和共享,支持在线编辑、录播资源、教学分析等功能。智慧管控则通过平安校园、可视对讲、紧急求助、视频监控等手段,保障校园安全。智慧办公则利用远程视讯、无纸化会议、数字会议等技术,提高行政效率和会议质量。 教育录播系统作为智慧校园的重要组成部分,提供了一套满足学校和教育局需求的解决方案。它包括标准课室、微格课室、精品课室等,通过自动五机位方案、高保真音频采集、一键式录课等功能,实现了优质教学资源的录制和共享。此外,录播系统还包括互动教学、录播班班通、教育中控、校园广播等应用,促进了教育资源的均衡化发展。 智慧办公的另一重点是无纸化会议和数字会议系统的建设,它们通过高效的文件管理、会议文件保密处理、本地会议的音频传输和摄像跟踪等功能,实现了会议的高效化和集中管控。这些系统不仅提高了会议的效率和质量,还通过一键管控、无线管控等设计,简化了操作流程,使得会议更加便捷和环保。 总之,智慧校园信息化系统解决方案通过整合先进的信息技术和教学资源,不仅提升了教育质量和管理效率,还为实现教育均衡化和资源共享提供了有力支持,推动了教育现代化的进程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值