线段树——数据结构的克星

线段树

树状数组不适合进行对区间的修改,对于区间修改我们一般使用线段树
在这里插入图片描述线段树每个节点存储时一段区间的值,这个视题目而定,每次把一段区间每次划分为两部分,新建两个节点来存储,直到叶子节点为止,所以说,所有叶子节点节点就是原数组
线段树的一个优化,每个节点设置一个lazy标记,如果lazy不为零表示下面的那些区间在使用时要进行修改,如果以后使用不到,就不进行修改了,这样会节省很多时间
线段是的根节点rt的两个孩子节点分别是rt<<1,rt<<1|1;

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
struct node{
	int e;
//	int l,r;
	int lazy;
	node()
	{
		e=lazy=0;
	}
//	int mid(){
//		return (r+1)>>1;
//	}
}tree[maxn<<1];
int a[maxn];
void push_up(int rt)
{
	tree[rt].e=tree[rt>>1].e+tree[rt>>1|1].e;
}
void build(int rt,int l,int r)
{
//	tree[rt].l=l;
//	tree[r].r=r;
	if(l==r)
	{
		tree[rt].e=a[l];
		return ;
	}
//	int m=tree[rt].mid();
	int m=(r+l)>>1;
	build(rt>>1,l,m);
	build(rt>>1|1,m+1,r);
	push_up(rt);
	
}
void push_down(int rt,int l,int r)
{
	if(!tree[rt].lazy)
	{
		tree[rt<<1].lazy+=tree[rt].lazy;
		tree[rt<<1|1].lazy+=tree[rt].lazy; 
		
		int m=(r+l)>>1;
		tree[rt<<1].e+=(m-r+1)*tree[rt].lazy;
		tree[rt<<1|1].e+=(r-m)*tree[rt].lazy;
		tree[rt].lazy=0;
	}
	
	
}
void update(int rt,int l,int r,int ll,int rr,int val)
{
	if(l>=ll&&r<=rr)
	{
		tree[rt].lazy+=val;
		tree[rt].e+=(r-l+1)*val; 
	}
	push_down(rt,l,r);
	int m=(r+l)>>1;
	if(m>=ll) update(rt<<1,l,m,ll,rr,val);
	if(m+1<=rr) update(rt<<1|1,m+1,r,ll,rr,val);
	push_up(rt);
}
int query(int rt,int l,int r,int ll,int rr)
{
	int res;
	if(l>=ll&&r<=rr)
	{
		return tree[rt].e;
	}
	push_down(rt,l,r);
	int m=(r+l)>>1;
	if(m>=ll) res+=query(rt<<1,l,m,ll,rr);
	if(m+1<=rr) res+=query(rt<<1|1,m+1,r,ll,rr);
		
	return res;
}



int main()
{
	
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值