【数据结构】线段树(点修区查)

数据结构-线段树(点修区查)


前置知识
  • 分治
  • 递归
  • 二叉树

思路

我们需要维护一个支持单点修改,区间查询的数据结构,并且要求在线,一般使用线段树解决。
线段树是一个二叉树形的数据结构。
线段树的思想很简单,就是将每个区间分治,构成一个树形结构,从而达到了 log ⁡ n \log n logn 的时间复杂度
以下是一个维护最小值的线段树。

具体实现也很简单,如下:

  1. 建树( build \text{build} build
    从根节点向下遍历,叶节点自更新,非叶节点使用儿子节点更新( pushup \text{pushup} pushup
  2. 更新( update \text{update} update
    从根节点向下遍历,类似二分查找查找至叶结点,叶节点自更新,非叶节点使用儿子节点更新( pushup \text{pushup} pushup
  3. 查询( query \text{query} query
    从根节点向下遍历,将区间分治到多个节点上,合并答案。如区间 [ 2 , 6 ] = [ 2 , 3 ] + [ 4 , 5 ] + [ 6 , 6 ] [2,6]=[2,3]+[4,5]+[6,6] [2,6]=[2,3]+[4,5]+[6,6],为节点 5 , 6 , 14 5,6,14 5,6,14 处的答案合并而来。

数据结构参数
  • 时间复杂度: O ( n log ⁡ n ) O(n\log n) O(nlogn)
  • 空间复杂度: O ( n ) O(n) O(n)

实现代码

以最小值线段树为例。

int t[MAXN*4];
#define ls p<<1
#define rs p<<1|1
void pushup(int p){
	t[p]=min(t[ls],t[rs]);
}
void build(int p,int l,int r){
	if (l==r){
		t[p]=a[l];
		return;
	}
	int mid=l+r>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(p);
}
void update(int p,int l,int r,int x,int y){
	if (l==r){
		t[p]=y;
		return;
	}
	int mid=l+r>>1;
	if (x<=mid) update(ls,l,mid,x,y);
	else update(rs,mid+1,r,x,y);
	pushup(p);
}
int query(int p,int l,int r,int x,int y){
	if (x<=l&&r<=y) return t[p];
	int mid=l+r>>1,ans=0x3f3f3f3f;
	if (x<=l) ans=min(ans,query(ls,l,mid,x,y));
	else ans=min(ans,query(rs,mid+1,r,x,y));
	return ans;
}

练习
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值