神马?是线段树!详解+例题:【线段树】最大值

首先,线段树,你细品……
em……
首先,线段树的作用是神马?
就是找一个区间内的最大值。

“那不是有手就行?”

但是,要替换!
就像这道非常BT的1.1.1例题:

在N(1<=N<=100000)个数A1…An组成的序列上进行M(1<=M<=100000)次操作,操作有两种:

(1)1 x y:表示修改A[x]为y;

(1)2 x y:询问x到y之间的最大值。

输入
第一行输入N(1<=N<=100000),表示序列的长度,接下来N行输入原始序列;接下来一行输入M(1<=M<=100000)表示操作的次数,接下来M行,每行为1 x y或2 x y

输出
对于每个操作(2)输出对应的答案。

样例输入
5
1
2
3
4
5
3
2 1 4
1 3 5
2 2 4

样例输出
4
5

还好,但是看看数据范围:
第一行输入N(1<=N<=100000),表示序列的长度,接下来N行输入原始序列;接下来一行输入**M(1<=M<=100000)**表示操作的次数,接下来M行,每行为1 x y或2 x y
还有手就行吗?

所以我们就要学习线段树,在此基础上加上修改操作的算法。

由于我是一名低IQ用户,所以这里就讲解一下最适合新手的做法。

1.建树

线段树就是一棵二叉树,每一个节点存储的是l(left)~r(right)里的最大值。

在这里插入图片描述
首先,线段树的存储方式肯定得是一维数组,所以我们就可以通过一位数组的每一个下标求出当前节点的l和r,直至l=r,然后我们就令:

if(l==r){
   
		a[i].maxn=b[l];//a是线段树,b是我们输入的数组
		return ;
}

然后其他的操作自然就是大名鼎鼎,宇宙无敌,举世无双,超级无敌牛逼的

二分查找!

别再问我二分查找是什么,快速排序总知道吧…

然而我们该怎么确定一个不是最底层节点的最大值呢?
仔细观察然后细品,然后就发现:

父亲节点=两个儿子节点的最大值!

a[i].maxn=max(a[2*i].maxn,a[2*i+1].maxn);

所以这里我们就完成了建树部分:

建树部分代码

//a数组存储的是线段树,b数组是输入的数组。
void make(int l,int r,int i){
   
	if(l==r){
   
		a[i].maxn=b[l];
		return ;
	}
	int m=(l+r)/2;
	make(l,m,2*i);
	make(m+1,r,2*i+1);
	a[i].maxn=max(a
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值