线段树算法讲解

线段树是一种高效的数据结构,适用于处理大型数组的区间查询与修改问题。本文介绍了线段树的基本概念,包括线段树的构建、push_up函数、单点修改及其查询,以及如何处理区间修改。通过lazy标记和push_down函数,实现了在单点修改和区间修改操作下保持线段树的正确性,从而降低时间复杂度。
摘要由CSDN通过智能技术生成

线段树算法讲解

问:给你一个长度为n的数组,然后询问m次,每次询问是给定两个数x,y。求在【x,y】区间的数之和。
也许你会说遍历,但若n为1e6,m为1e3呢?这是可以用一种数据结构——线段树。
线段树的每一个点维护一个[l,r)的区间。长这样:
在这里插入图片描述图中,数组长度为6,第一个节点维护的是【1,6】的最大值,左节点维护的是【1,3】的最大值,以此类推,直至叶子节点。
下面,以求区间和为例来进一步说明。
定义:

const int maxn = 1e5 + 10;
struct node{
   
	int l, r;//左右节点 
	int data;//存储的值 
	int mid()
	{
   
		return (l + r) >> 1;
	}
}sum[maxn << 2];//一般开四倍空间 

线段树的构建
void build(int root, int l, int r)
{
   
	sum[root].l = l, sum[root].r = r;//给每个节点所维护的区间赋值 
	if(sum[root].l == sum[root].r)//到达叶子节点 
	{
   
		sum[root].data = a[sum[root].l];
		return;
	}
	int mid = sum[root].mid();
	build(root << 1, l, mid);//左右递归建树 
	build(root << 1 | 1, mid + 1, r);
	push_up(root);//精髓所在 
}

观察代码,可以发现,线段树的构建是不断地递归直至叶子节点赋值。叶子节点赋值之后用push_up函数为其父亲节点赋值。

push_up函数
void push_up(int root)
{
   
	sum[root].data = sum[root << 1].data + sum[root << 1 | 1].data;
}
单点修改
void update(int root, int p, int v)//p位置的值加v 
{
   
	if(sum[root].l == sum[root].r)//找到需要修改的节点 
	{
   
		sum[root].data += v;
		return;
	}
	int mid = sum[root].mid();
	if(p <= mid)//若在左子节点内 
		update(root << 1, p, v);
	else if(p > mid)//若在右子节点内 
		update(root << 1 | 1, p, v);
	push_up(root);//更新父节点 
}
单点修改情况下的查询
int query(int root, int l, int r)
{
   
	int ans = 0;
	if(sum[root].l >= l && sum[root].r <= r)
	{
   
		return sum[root].data;
	}
	int mid = sum[root].mid();
	if(mid >= l)//若所查询区间和左子节点区间有交集 
		ans += query(root << 1, l, r);
	if(mid + 1 <= r)//若和右子节点区间有交集 
		ans += query(root << 1 | 1, l, r);
	return ans;
}

上面是单点修改的情况,下面讲解区间修改
在对某个区间修改时需要用到lazy标记。当使用lzay标记某个区间时,此区间之上的区间显示的内容是修改过的,但其子区间没有被修改,当需要用到子区间时会通过push_down函数进行修改,这样做主要是为了减少时间复杂度。

void update(int root, int l, int r, 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值