线段树

我们先来看一个线段树长什么样子:
在这里插入图片描述
看到它和普通的树有什么区别的嘛,对,它胖 它的每个节点上存放着一个区间,当需要修改一个区间的值时,它能够快速的定位,当找到询问所包含的完整区间后不会再向下细分,这样子就将时间复杂度变成了log级别,我们来通过模板题看一下线段树的具体操作
题目链接
首先是建树,由于线段树的每个节点要存它的区间左右端点和一些要用的值,就不能简单只用一个数组,为了方便我们用一个struct来包含这些内容

const int N=1e5+10;
struct Node{
	int L, R;//左右端点标记
	LL add, sum;//sum为这个区间的和,add为懒标记,后面会说的
	int len(){//省点事,输出这个区间中有多少个数
		return R-L+1;
	}
}tree[N*4];//一般线段树开四倍长度即可

然后是建树,与归并排序的思想有点相似

void Up(int p)//向上归并
{
	tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
}
void build(int L, int R, int p)//建树
{
	tree[p].L=L, tree[p].R=R;
	if(L==R)
	{
		tree[p].add=0;
		tree[p].sum=A[L];
		return ;
	}
	int mid=(L+R)>>1;//先建左右子树,再归并回来
	build(L, mid, p<<1);
	build(mid+1, R, p<<1|1);
	Up(p);
}

谈完建树就要谈线段树的操作了,线段树的操作一共有2个,修改与查询(在这题中为求和)我们先讲修改,这里就要谈到线段树修改的一个节省时间的操作了:懒标记。有时候一些修改在下面的某些查询中或者查询的正好包括这个修改的区间,不用将修改放到一个个对应的最低端的点上就能返回正确答案,这时若把这些修改全部放到最低端的点上没有任何用,反而浪费时间。我们就可以在完整包含这些点的区间上打上一个标记,等到需要下放时再将这些标记释放下去

void Down(int p){//懒标记的释放
	LL &t=tree[p].add;
	if(t==0) return;//没有懒标记
	tree[p<<1].add+=t;
	tree[p<<1].sum+=tree[p<<1].len()*t;
	tree[p<<1|1].add+=t;
	tree[p<<1|1].sum+=tree[p<<1|1].len()*t;
	t=0;
}
void update(int L, int R, int a, int p)
{
	if(tree[p].L==L&&tree[p].R==R)//若此区间刚好等于修改区间,则在此添加懒标记,否则释放此节点上的懒标记,同时向下搜寻并起来刚好等于修改区间的各个区间,还是使用了 归并的思想
	{
		tree[p].add+=a;
		tree[p].sum+=a*(R-L+1);
		return;
	}
	Down(p);
	int mid=(tree[p].L+tree[p].R)>>1;
	if(R<=mid) update(L, R, a ,p<<1);
	else if(L>mid) update(L, R, a, p<<1|1);
	else {
		update(L, mid, a, p<<1);
		update(mid+1, R, a, p<<1|1);
	}
	Up(p);
}

然后就是求和了,求和时跟添加时差不多,若查询的区间与当前区间有交集且交集不为此区间,则释放此区间懒标记,代码如下:

typedef  long long LL;
LL query(int L, int R, int p)//题目数据较大,要用long long
{
	if(tree[p].L==L&&tree[p].R==R)
	{
		return tree[p].sum;
	}
	Down(p);
	int mid=(tree[p].L+tree[p].R)>>1;
	if(R<=mid) return query(L, R, p<<1);
	else if(L>mid) return query(L ,R, p<<1|1);
	else return query(L, mid, p<<1)+query(mid+1, R, p<<1|1);
}

然后稍加润色,完整的题目代码如下

#include <bits/stdc++.h>
using namespace std;
typedef  long long LL;
const int N=1e5+10;
LL A[N];
struct Node{
	int L, R;
	LL add, sum;
	int len(){
		return R-L+1;
	}
}tree[N*4];
void Up(int p)
{
	tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
}
void Down(int p){
	LL &t=tree[p].add;
	if(t==0) return;
	tree[p<<1].add+=t;
	tree[p<<1].sum+=tree[p<<1].len()*t;
	tree[p<<1|1].add+=t;
	tree[p<<1|1].sum+=tree[p<<1|1].len()*t;
	t=0;
}
void build(int L, int R, int p)
{
	tree[p].L=L, tree[p].R=R;
	if(L==R)
	{
		tree[p].add=0;
		tree[p].sum=A[L];
		return ;
	}
	int mid=(L+R)>>1;
	build(L, mid, p<<1);
	build(mid+1, R, p<<1|1);
	Up(p);
}
void update(int L, int R, int a, int p)
{
	if(tree[p].L==L&&tree[p].R==R)
	{
		tree[p].add+=a;
		tree[p].sum+=a*(R-L+1);
		return;
	}
	Down(p);
	int mid=(tree[p].L+tree[p].R)>>1;
	if(R<=mid) update(L, R, a ,p<<1);
	else if(L>mid) update(L, R, a, p<<1|1);
	else {
		update(L, mid, a, p<<1);
		update(mid+1, R, a, p<<1|1);
	}
	Up(p);
}
LL query(int L, int R, int p)
{
	if(tree[p].L==L&&tree[p].R==R)
	{
		return tree[p].sum;
	}
	Down(p);
	int mid=(tree[p].L+tree[p].R)>>1;
	if(R<=mid) return query(L, R, p<<1);
	else if(L>mid) return query(L ,R, p<<1|1);
	else return query(L, mid, p<<1)+query(mid+1, R, p<<1|1);
}
int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++)
	{
		scanf("%lld", &A[i]);
	}
	build(1, n, 1);
	int c;
	int R, L, X;
	for(int i=0; i<m; i++)
	{
		scanf("%d", &c);
		if(c==2) 
		{
			scanf("%d%d", &L, &R);
			printf("%lld\n", query(L, R, 1));
		}
		else {
			scanf("%d%d%d", &L, &R, &X);
			update(L, R, X, 1);
		}
	}
	return 0;
}

其实线段树是有一定的模板在的,除了线段树节点内的内容,up()与down()函数以及query()中返回的东西要根据题目思考,其他都不需要更换。线段树的优点还是要多通过写这个来理解啊.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水利改革发展 中国政府高度重视水利建设,将水利作为国家基础设施建设的优先领域。政策文件强调了防洪抗旱、水资源管理、水环境保护和水生态修复等方面的全面要求,推动了水利信息化的发展。 智慧水利建设目标 智慧水利的建设目标是通过数据共享、应用惠民、应急预警等手段,打破信息孤岛,提升应急抢险协作能力,加强水利数据在惠民信息化方面的应用。同时,提出了共享联动化、解决信息安全问题、提高水利信息科技创新能力等目标。 智慧水利建设模式 智慧水利的建设模式包括构建统一平台、数据中心、信息整合平台、决策支持系统等,以实现水利、海洋、环保等政府部门和公众的信息共享和服务。此外,还包括了云计算虚拟化、网络传输、采集工程等多个方面的技术应用。 智慧水利应用实例 智慧水利的应用实例包括视频水文工程监控、多要素一体化检测设备、汛情预警智能联动、三防决策指挥、河长综合信息展示等。这些应用通过集成GIS、互联网地图服务、物联网设备等技术,实现了对水利设施的实时监控、数据分析和应急响应。 成功案例与展望 智慧水利的成功案例展示了通过视频监控、预警信息发布、移动办公信息APP等技术,有效提升了灾害应对能力、水资源管理和河长制的实施效果。这些案例表明,智慧水利的建设不仅提高了水利管理的效率和水平,也为未来的水利信息化发展提供了方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值