线段树

线段树是树状数组的升级版,线段树等于把一个[l,r]的区间,分成很多个小区间,这样方便我们查找一段区间内的信息,不用暴力去跑一遍。

线段树的存储结构:
在这里插入图片描述
首先是最基本的建树(用的是递归):
(求一段区间的和)

void pushup(int rt){	// 更新当前结点的值,这里写的是求一段区间的和
    sum[rt] = sum[rt << 1] + sum[r << 1 | 1]; //	当前根的值 = 左子树的值+右子树的值
}
void build(int l, int r, int rt){ // l,r指的是区间,通常是[1,n],rt是当前区间的下标
    if(l == r){
        sum[rt] = a[l];	//sum数组用来存储当前区间的信息(我们所需要的信息)
        return ;
    }

    int m = (l + r) >> 1;	// 二分,建左子树和右子树
    build(l, m, rt << 1);	// rt << 1 == rt * 2	rt << 1 | 1 == rt * 2 + 1
    build(m+1, r, rt << 1 | 1);
    pushup(rt);	// 这里需要更新当前结点的信息。
}

接下来就是单点修改(通常线段树的题目都会要求你修改某一个点或者修改某一区间所有值):

void Add(int L, int l, int r, int x,int rt){	//L大区间的左界,l,r是你目前的小区间,x是要求修改的值,rt是当前区间下标
    if(l == r){
        sum[rt] += x;
        return ;
    }

    int m = (l + r) >> 1;
    if(L < m) // 如果m > 大区间左界就要向左子树调用,相反向右子树
    	Add(L, l, m+1, x, rt << 1);
    else
    	Add(L, m+1, l, x, rt << 1 | 1);
    pushup(rt); // 更新当前区间的信息
}

区间修改:

例如一个区间的所有数都+1,你每个数去+1的话就特别慢,线段树的优势就在此处,可以先用一个延迟数组存下这个区间里的数需要+1

void PushDown(int rt,int ln,int rn){	// ln,rn是左子树,右子树数的数量
	if(Add[rt]){	//如果延迟数组表示区间需要改变
		Add[rt<<1]+=Add[rt];	//左右区间继承延迟
		Add[rt<<1|1]+=Add[rt];
		Sum[rt<<1]+=Add[rt]*ln;	//当前区间消除延迟
		Sum[rt<<1|1]+=Add[rt]*rn;
		Add[rt]=0;	//消除延迟
	}
}
void Add(int L,int R,int C,int l,int r,int rt){
	if(L <= l && r <= R){
		Sum[rt]+=C*(r-l+1);
		Add[rt]+=C;
		return ; 
	}
	int m=(l+r)>>1;
	PushDown(rt,m-l+1,r-m);
	if(L <= m) Add(L,R,C,l,m,rt<<1);
	if(R >  m) Add(L,R,C,m+1,r,rt<<1|1); 
	PushUp(rt);
}

最后一步就是查询了:
(区间查询)

int query(int L, int R, int l, int r, int rt){
    if(L <= l && r <= R){
        return sum[rt];
    }

    int m = (l + r) >> 1,ans = 0;
    pushdown(rt);	//还需要消除一下延迟,不然可能错
    if(L >= l)
    	ans += query(L, R, l, m, rt << 1);
    if(R < r)
    	ans += query(L, R, m+1, r, rt << 1 | 1);
    return ans;
}

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值