线段树

【c++提高1】数据结构之线段树详解 线段树的思想是将一个区间[1, n]划分成两个区间: [1, n/2]和[n/2+1, n],接下来继续划分: [1, n/4], [n/4+1,n/2]和[n/2+1, n/2+n/4-1], [n/2+n/4,n] …示例:n = 81.pushup函数2.pushdown3.build4.modify5.query1.线段树的儿子存储2.线段树的节点信息存储 定义一个结构体,里面存储改节点信息和当前这个节点所管辖的区间的左右端点。1.建树函数build 递归建树。 怎样判断当前节点是叶子节点呢?2.查 阅读详情

一 概述

线段树,类似区间树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(logn)。

线段树的每个节点表示一个区间,子节点则分别表示父节点的左右半区间,例如父亲的区间是[a,b],那么(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b]。

二 从一个例子理解线段树

下面我们从一个经典的例子来了解线段树,问题描述如下:从数组arr[0…n-1]中查找某个数组某个区间内的最小值,其中数组大小固定,但是数组中的元素的值可以随时更新。

对这个问题一个简单的解法是:遍历数组区间找到最小值,时间复杂度是O(n),额外的空间复杂度O(1)。当数据量特别大,而查询操作很频繁的时候,耗时可能会不满足需求。

另一种解法:使用一个二维数组来保存提前计算好的区间[i,j]内的最小值,那么预处理时间为O(n^2),查询耗时O(1), 但是需要额外的O(n^2)空间,当数据量很大时,这个空间消耗是庞大的,而且当改变了数组中的某一个值时,更新二维数组中的最小值也很麻烦。

我们可以用线段树来解决这个问题:预处理耗时O(n),查询、更新操作O(logn),需要额外的空间O(n)。根据这个问题我们构造如下的二叉树

叶子节点是原始组数arr中的元素
非叶子节点代表它的所有子孙叶子节点所在区间的最小值
例如对于数组[2, 5, 1, 4, 9, 3]可以构造如下的二叉树(背景为白色表示叶子节点,非叶子节点的值是其对应数组区间内的最小值,例如根节点表示数组区间arr[0…5]内的最小值是1):

由于线段树的父节点区间是平均分割到左右子树,因此线段树是完全二叉树,对于包含n个叶子节点的完全二叉树,它一定有n-1个非叶节点,总共2n-1个节点,因此存储线段是需要的空间复杂度是O(n)。那么线段树的操作:创建线段树、查询、节点更新 是如何运作的呢(以下所有代码都是针对求区间最小值问题)?

2.1 创建线段树

对于线段树我们可以选择和普通二叉树一样的链式结构。由于线段树是完全二叉树,我们也可以用数组来存储,下面的讨论及代码都是数组来存储线段树,节点结构如下(注意到用数组存储时,有效空间为2n-1,实际空间确不止这么多,比如上面的线段树中叶子节点1、3虽然没有左右子树,但是的确占用了数组空间,实际空间是满二叉树的节点数目: 2 * 2 ^{\lceil \log_2{n} \rceil} - 1, \lceil \log_2{n} \rceil 是树的高度,但是这个空间复杂度也是O(n)的 )。

struct SegTreeNode
{
  int val;
};

定义包含n个节点的线段树 SegTreeNode segTree[n],segTree[0]表示根节点。那么对于节点segTree[i],它的左孩子是segTree[2*i+1],右孩子是segTree[2*i+2]。

我们可以从根节点开始,平分区间,递归的创建线段树,线段树的创建函数如下:

 const int MAXNUM = 1000;
 struct SegTreeNode
{
     int val;
 }segTree[MAXNUM];//定义线段树

 /*
功能:构建线段树
root:当前线段树的根节点下标
arr: 用来构造线段树的数组
istart:数组的起始位置
iend:数组的结束位置
*/
void build(int root, int arr[], int istart, int iend)
{
   if(istart == iend)//叶子节点
      segTree[root].val = arr[istart];
  else
   {
       int mid = (istart + iend) / 2;
        build(root*2+1, arr, istart, mid);//递归构造左子树
      build(root*2+2, arr, mid+1, iend);//递归构造右子树
       //根据左右子树根节点的值,更新当前根节点的值
        segTree[root].val = min(segTree[root*2+1].val, segTree[root*2+2].val);
     }
 }

2.2 查询线段树

已经构建好了线段树,那么怎样在它上面超找某个区间的最小值呢?查询的思想是选出一些区间,使他们相连后恰好涵盖整个查询区间,因此线段树适合解决“相邻的区间的信息可以被合并成两个区间的并区间的信息”的问题。代码如下,具体见代码解释

这里写代码片

举例说明(对照上面的二叉树):

1、当我们要查询区间[0,2]的最小值时,从根节点开始,要分别查询左右子树,查询左子树时节点区间[0,2]包含在查询区间[0,2]内,返回当前节点的值1,查询右子树时,节点区间[3,5]和查询区间[0,2]没有交集,返回正无穷INFINITE,查询结果取两子树查询结果的较小值1,因此结果是1.

2、查询区间[0,3]时,从根节点开始,查询左子树的节点区间[0,2]包含在区间[0,3]内,返回当前节点的值1;查询右子树时,继续递归查询右子树的左右子树,查询到非叶节点4时,又要继续递归查询:叶子节点4的节点区间[3,3]包含在查询区间[0,3]内,返回4,叶子节点9的节点区间[4,4]和[0,3]没有交集,返回INFINITE,因此非叶节点4返回的是min(4, INFINITE) = 4,叶子节点3的节点区间[5,5]和[0,3]没有交集,返回INFINITE,因此非叶节点3返回min(4, INFINITE) = 4, 因此根节点返回 min(1,4) = 1。

2.3单节点更新

单节点更新是指只更新线段树的某个叶子节点的值,但是更新叶子节点会对其父节点的值产生影响,因此更新子节点后,要回溯更新其父节点的值。

1 /*
2 功能:更新线段树中某个叶子节点的值
3 root:当前线段树的根节点下标
4 [nstart, nend]: 当前节点所表示的区间
5 index: 待更新节点在原始数组arr中的下标
6 addVal: 更新的值(原来的值加上addVal)
7 */
8 void updateOne(int root, int nstart, int nend, int index, int addVal)
9 {
10 if(nstart == nend)
11 {
12 if(index == nstart)//找到了相应的节点,更新之
13 segTree[root].val += addVal;
14 return;
15 }
16 int mid = (nstart + nend) / 2;
17 if(index <= mid)//在左子树中更新
18 updateOne(root*2+1, nstart, mid, index, addVal);
19 else updateOne(root*2+2, mid+1, nend, index, addVal);//在右子树中更新
20 //根据左右子树的值回溯更新当前节点的值
21 segTree[root].val = min(segTree[root*2+1].val, segTree[root*2+2].val);
22 }
比如我们要更新叶子节点4(addVal = 6),更新后值变为10,那么其父节点的值从4变为9,非叶结点3的值更新后不变,根节点更新后也不变。

2.4 区间更新

区间更新是指更新某个区间内的叶子节点的值,因为涉及到的叶子节点不止一个,而叶子节点会影响其相应的非叶父节点,那么回溯需要更新的非叶子节点也会有很多,如果一次性更新完,操作的时间复杂度肯定不是O(lgn),例如当我们要更新区间[0,3]内的叶子节点时,需要更新出了叶子节点3,9外的所有其他节点。为此引入了线段树中的延迟标记概念,这也是线段树的精华所在。

延迟标记:每个节点新增加一个标记,记录这个节点是否进行了某种修改(这种修改操作会影响其子节点),对于任意区间的修改,我们先按照区间查询的方式将其划分成线段树中的节点,然后修改这些节点的信息,并给这些节点标记上代表这种修改操作的标记。在修改和查询的时候,如果我们到了一个节点p,并且决定考虑其子节点,那么我们就要看节点p是否被标记,如果有,就要按照标记修改其子节点的信息,并且给子节点都标上相同的标记,同时消掉节点p的标记。

因此需要在线段树结构中加入延迟标记域,本文例子中我们加入标记与addMark,表示节点的子孙节点在原来的值的基础上加上addMark的值,同时还需要修改创建函数build 和 查询函数 query,修改的代码用红色字体表示,其中区间更新的函数为update,代码如下:

1 const int INFINITE = INT_MAX;
2 const int MAXNUM = 1000;
3 struct SegTreeNode
4 {
5 int val;
6 int addMark;//延迟标记
7 }segTree[MAXNUM];//定义线段树
8
9 /*
10 功能:构建线段树
11 root:当前线段树的根节点下标
12 arr: 用来构造线段树的数组
13 istart:数组的起始位置
14 iend:数组的结束位置
15 */
16 void build(int root, int arr[], int istart, int iend)
17 {
18 segTree[root].addMark = 0;//—-设置标延迟记域
19 if(istart == iend)//叶子节点
20 segTree[root].val = arr[istart];
21 else
22 {
23 int mid = (istart + iend) / 2;
24 build(root*2+1, arr, istart, mid);//递归构造左子树
25 build(root*2+2, arr, mid+1, iend);//递归构造右子树
26 //根据左右子树根节点的值,更新当前根节点的值
27 segTree[root].val = min(segTree[root*2+1].val, segTree[root*2+2].val);
28 }
29 }
30
31 /*
32 功能:当前节点的标志域向孩子节点传递
33 root: 当前线段树的根节点下标
34 */
35 void pushDown(int root)
36 {
37 if(segTree[root].addMark != 0)
38 {
39 //设置左右孩子节点的标志域,因为孩子节点可能被多次延迟标记又没有向下传递
40 //所以是 “+=”
41 segTree[root*2+1].addMark += segTree[root].addMark;
42 segTree[root*2+2].addMark += segTree[root].addMark;
43 //根据标志域设置孩子节点的值。因为我们是求区间最小值,因此当区间内每个元
44 //素加上一个值时,区间的最小值也加上这个值
45 segTree[root*2+1].val += segTree[root].addMark;
46 segTree[root*2+2].val += segTree[root].addMark;
47 //传递后,当前节点标记域清空
48 segTree[root].addMark = 0;
49 }
50 }
51
52 /*
53 功能:线段树的区间查询
54 root:当前线段树的根节点下标
55 [nstart, nend]: 当前节点所表示的区间
56 [qstart, qend]: 此次查询的区间
57 */
58 int query(int root, int nstart, int nend, int qstart, int qend)
59 {
60 //查询区间和当前节点区间没有交集
61 if(qstart > nend || qend < nstart)
62 return INFINITE;
63 //当前节点区间包含在查询区间内
64 if(qstart <= nstart && qend >= nend)
65 return segTree[root].val;
66 //分别从左右子树查询,返回两者查询结果的较小值
67 pushDown(root); //—-延迟标志域向下传递
68 int mid = (nstart + nend) / 2;
69 return min(query(root*2+1, nstart, mid, qstart, qend),
70 query(root*2+2, mid + 1, nend, qstart, qend));
71
72 }
73
74 /*
75 功能:更新线段树中某个区间内叶子节点的值
76 root:当前线段树的根节点下标
77 [nstart, nend]: 当前节点所表示的区间
78 [ustart, uend]: 待更新的区间
79 addVal: 更新的值(原来的值加上addVal)
80 */
81 void update(int root, int nstart, int nend, int ustart, int uend, int addVal)
82 {
83 //更新区间和当前节点区间没有交集
84 if(ustart > nend || uend < nstart)
85 return ;
86 //当前节点区间包含在更新区间内
87 if(ustart <= nstart && uend >= nend)
88 {
89 segTree[root].addMark += addVal;
90 segTree[root].val += addVal;
91 return ;
92 }
93 pushDown(root); //延迟标记向下传递
94 //更新左右孩子节点
95 int mid = (nstart + nend) / 2;
96 update(root*2+1, nstart, mid, ustart, uend, addVal);
97 update(root*2+2, mid+1, nend, ustart, uend, addVal);
98 //根据左右子树的值回溯更新当前节点的值
99 segTree[root].val = min(segTree[root*2+1].val, segTree[root*2+2].val);
100 }
区间更新举例说明:当我们要对区间[0,2]的叶子节点增加2,利用区间查询的方法从根节点开始找到了非叶子节点[0-2],把它的值设置为1+2 = 3,并且把它的延迟标记设置为2,更新完毕;当我们要查询区间[0,1]内的最小值时,查找到区间[0,2]时,发现它的标记不为0,并且还要向下搜索,因此要把标记向下传递,把节点[0-1]的值设置为2+2 = 4,标记设置为2,节点[2-2]的值设置为1+2 = 3,标记设置为2(其实叶子节点的标志是不起作用的,这里是为了操作的一致性),然后返回查询结果:[0-1]节点的值4;当我们再次更新区间[0,1](增加3)时,查询到节点[0-1],发现它的标记值为2,因此把它的标记值设置为2+3 = 5,节点的值设置为4+3 = 7;

其实当区间更新的区间左右值相等时([i,i]),就相当于单节点更新,单节点更新只是区间更新的特例。

三 线段树实战

求区间的最大值、区间求和等问题都是采用类似上面的延迟标记域。下面会通过acm的一些题目来运用一下线段树。

C++ 线段树 线段树基本常识 线段树是一种二叉搜索树(即每个节点最多有两颗子树),与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。 如下图,就是一颗 [1,10] 的线段树的分解过程: 由图可得出一个结论,线段树的最大深度不超过,且每一颗线段树需要 4*n 的辅助空间,如果没有开到 4*n ,那就完美 RE 了!!! 线段树的的存储 线段树采用的是堆式储存法,即编号为 k 的节点的做儿子为 k... 阅读详情

相关推荐

线段树详解(包含加法线段树、乘法线段树及区间根号线段树,简单易懂)

线段树及简单应用。

qi_programmer的博客 2582

线段树算法(C++/C)

本文主要介绍的是算法中的线段树算法,简单易懂详细

gaoqiandr的博客 2573

线段树合并与线段树分裂

线段树合并是指建立一棵新的线段树,这棵线段树的每个节点都是两棵原线段树对应节点合并后的结果。线段树分裂实质上是线段树合并的逆过程。线段树分裂只适用于有序的序列,无序的序列是没有意义的,常用在动态开点的权值线段树。线段树分裂与线段树合并密不可分,一般来说没有只分裂不合并的题。的救灾粮,问所有操作结束后每个节点类型最多的救灾粮是那种。一棵树,点有点权,问每个节点的子树内有多少节点点权比它大。从这棵树的根节点开始递归分裂,当节点不存在时,递归结束。显然,对于两颗满的线段树,合并操作的复杂度是。

conti123的博客 934

高级数据结构:线段树入门(c++实现 + 详解)

线段树是一种高级数据结构,与树状数组一样,被用来处理区间查询,修改问题,并且线段树的最大优点是对动态数据的处理十分高效。关于树状数组,可以看我这篇博文的介绍: 高级数据结构:树状数组详解来看看线段树能处理的问题:线段树是具有以下形态的二叉树,其中树上的每个节点都是一个线段区间 。看图可以发现线段树的几个特征:这颗二叉树是采用分治法来划分区间,并且构建子树的,左右子树各一半。这颗二叉树的每个节点都是一个线段区间,非叶子节点的线段区间是一段不相等的区间,叶子节点的线段区间的只包含一个元素。这颗二叉树是一颗完全二

ylh的博客 7141

二维线段树(线段树套线段树)

由于网上的其它博客对初学者非常不友好,所以我就来写一篇博客帮助萌新们快速入门树套树啦。所谓线段树套线段树就是在第一棵线段树的每一个结点上再开一颗线段树,第一棵线段树用来维护第一维的数据,再用第一棵线段树上新开的线段树来维护第二维的数据。是不是没听懂呢,下面我们直接上图: 这就是树套树大概的模样,横线上面是第一棵线段树,下面是对第一棵线段树的每一个结点新开的线段树,就像是每一个点内都套着一棵线段树一样,那么二维线段树就可以用来维护平面信息下面看一道例题: 陌上花开 首先对第一维进行排序,然后用树套树进行处理

NEUQ_snowy的博客 4432

Vectorless dynamic动态功耗分析——Voltus

power 计算工具会根据设计信息和用户提供的activity和switching约束来生成虚拟的worst-case的power vector,难点在于哪些instances视为switching,在没有仿真的前提下如何确定开关的时间,使用timing文件(TWF)

qq_44347276的博客 2789

【学习笔记】详解线段树(浅显易懂,匠心之作,图文并茂)

超详解线段树(浅显易懂,几乎涵盖所有线段树类型讲解,匠心之作,图文并茂)

weq2011的博客 3万+

致远OA系统表单相关操作记录(一)

致远OA系统表单相关操作

weixin_59666050的博客 6101

【算法】线段树

几乎是算法竞赛最常用的数据结构了,它主要用于(要求满足结合律)。与树状数组相比,它可以实现的,还可以同时(加、乘),更具通用性。如题,已知一个数列,你需要进行下面两种操作:1.将某区间每一个数加上x2.求出某区间每一个数的和第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

weixin_73366312的博客 1808

用FPGA在HDMI上显示自定义字符:从COE文件到OSD叠加的保姆级教程

本文详细介绍了如何在FPGA上实现HDMI视频流的OSD字符叠加技术,从COE文件生成到动态区域控制的完整流程。通过Verilog代码示例和实战技巧,帮助开发者掌握字符ROM设计、像素坐标追踪和动态混合等核心技术,适用于视频监控、系统状态显示等应用场景。

weixin_28720767的博客 231

DIY T12烙铁头驱动难题:用几个电容二极管,搞定NMOS上管驱动(附Multisim仿真)

本文详细介绍了如何利用电荷泵电路解决DIY T12烙铁头驱动中的NMOS上管驱动难题。通过巧妙组合电容和二极管,构建低成本高效的升压电路,实现栅极高压驱动需求。文章包含具体电路设计、元件选型建议、实际搭建注意事项以及Multisim仿真验证,为电子爱好者提供了一套完整的解决方案。

weixin_33640562的博客 334

【线段树】线段树入门之入门

线段树的入门级 总结       线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。       对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。       使用线段树可以

生命有一种绝对 4万+

深入解析ADC采样电容:从充电误差到LSB精度的关键设计

本文深入解析了ADC采样电容在模数转换中的核心作用,重点探讨了充电时间常数与采样误差的博弈关系。通过推导最小采样时间公式,揭示了精度、速度、源阻抗与内部电容之间的制约关系,并提供了从理论计算到外部驱动电路设计的实战指南,是确保ADC达到LSB精度的关键。

android的专栏 1103

线段树详解

1. 什么是线段树 顾名思义 , 线段树是一棵二叉树 , 但不同的是这棵树的结点储存的值是一个数列中 [l,r][l,r][l,r] 的某个需要的值 (例如,求和,求最大值,求最小值) 这是一棵典型的线段树 ,其性质是 : 若其中一子节点编号为 aaa , 则该节点左儿子编号为 2a2a2a , 其右儿子编号为 2a+12a+12a+1 2. 线段树的用处 线段树的用处就是,对编号连续的一些点进行修改或者统计操作,修改和统计的复杂度都是 O(log2n)O(log_2 n)O(log2​n). 3.

orz 1万+

CS 188 Project3(RL) Q10:Approximate Q-Learning

实现一个近似的Q-learning学习代理,它学习状态特征的权重,其中许多状态可能共享相同的特征。在qlearningAgents.py中的ApproximateQAgent类中编写实现,它是PacmanQAgent的子类。 注:近似Q-learning学习假设在状态和动作对上存在一个特征函数f(s,a),它产生一个向量f1(s,a) .. fi(s,a) .. fn(s,a)特征值。我们在fe...

大模型与Agent智能体 2655

KEPServerEX作为MQTT客户端

打开软件: 测试没有连接上MQTT代理。

低码开发 1681

【线段树模板以及Codeforces线段树专题总结】

线段树模板 //线段树一般用来解决可合并的区间问题 //树上维护子树区间的问题也可以通过dfs序+线段树去维护 //不要忘记build,dfs序问题build时注意下标 //数组记得开4倍,push_down一定要想好顺序 //对于每个问题,我们只要考虑清楚push_down和push_up的写法即可 //当问题不好处理的时候,想象一下对于单次询问暴力的做法,再进行区间操作 struct T { ...

lajiyuan的博客 4090

飞行机械臂设计

其后对飞行机械臂系统的机 理模型和基于 ADAMS 的物理模型进行了控制系统的搭建,对于机理模 型,设计了三个输入通道,分别是俯仰力矩,翻滚力矩与偏航力矩,控 制量为翻滚角,俯仰角,偏航角。四旋翼无人机自身具有独特的优势,在无人机上增加机械臂,整个 机体系统相当于一架空中行动自如的空中机器人,可以适应更多的应用场合,能够实现空中抓取,运输载荷,巡航监视等任务。的函数模块如图 4-8 所示,可见输入为 U1,U2,U3,U4,分别对应总力矩,俯仰力矩,翻滚力矩,偏航力矩,控制 量为俯仰角,翻滚角,偏航角。

coldmood77的博客 2914

线段树及线段树模板

线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为Olog⁡NO(\log N)OlogN。而未优化的空间复杂度为2N2N2N,实际应用时一般还要开空间为4N4N4N的数组以免越界,因此有时需要离散化让空间压缩。线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。

AllenAC的博客 1234

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

有关线段树合并

目录:一:线段树合并概念二:线段树合并应用。

2509_93020071的博客 2195

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

线段树合并

文章目录前置芝士线段树合并概念merge题目描述输入格式输出格式代码 前置芝士 权值线段树 动态开点线段树 线段树合并的全称为动态开点权值线段树合并 加个链接 线段树合并 概念 顾名思义,就是建立一棵新的线段树保存原有的两颗线段树的信息。 merge 线段树合并所完成的操作就是:在相同区间内,对应位置相加。 合并方式主要如下:两个相同区间的节点 p{p}p 和 q{q}q,合并区间 [l,r]{[l,r]}[l,r]。 若 p{p}p 和 q{q}q 有一者为 0{0}0,则另一者为根。 若 l=

Cauchy的博客 4223

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

详解线段树

但是在做题的时候还是会对模板进行修改,修改的点主要在区间val的意义上,我们这里模板里面val代表的是区间和,但后面题目里面可能是 区间最大值 、区间最小值…,但是万变不离其宗,线段树的结构是不会变的。

潜心钻研技术 1353

线段树之zkw

线段树之zkw,主要的作用是用来卡常,虽然平时的使用似乎不太多,但是可以学习一下。

月巴虫丰博客 2989

详细图文——线段树

线段树的基本认识和代码。如果您是为了竞赛,那么此文章一定不适合您;如果您只是好奇,或者想了解一下,点进来吧!!^_^通过此文您能了解什么是线段树,线段树的使用场景和自己实现线段树。

带翅膀的猫的博客 3748
下一篇: 堆排序heapsort
mscdj
博客等级 码龄16年 0粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值