首页 > 编程语言 >算法:线段树

算法:线段树

时间:2023-10-03 17:11:36浏览次数:65  
标签:rt 正整数 int 线段 mid 算法 节点

算法:线段树

哦吼!终于来学线段树啦~~

拖了好久都没有敢学,主要是基础知识点不熟,代码能力太弱。但是现在已经是时候了。

来看:

线段树(Segment Tree)几乎是算法竞赛最常用的数据结构了,它主要用于维护 区间信息 (要求满足结合律)。与树状数组相比,它可以实现 \(O(log⁡\ n)\) 的 区间修改,还可以同时支持多种操作(加、乘),更具通用性。

线段树入门 - 敌兵布阵

题目描述

第一行有两个正整数 \(N\) 和 \(M\),分别表示敌人有 \(N\) 个工兵营地,有 \(M\) 条命令。

第二行有 \(N\) 个正整数,第 \(i\) 个正整数 \(a_i\) 代表第 i 个工兵营地里开始时有 \(a_i\) 个人。

接下来有 \(M\) 行,每行有一条命令,命令有 \(3\) 种形式:

(1) \(Add \ i \ j\),其中 \(i\) 和 \(j\) 为正整数,表示第 \(i\) 个营地增加 \(j\) 个人;

(2) \(Sub \ i \ j\),其中 \(i\) 和 \(j\) 为正整数,表示第 \(i\) 个营地减少 \(j\) 个人;

(3) \(Query\ i\ j\),其中 \(i\) 和 \(j\) 为正整数,表示询问第 \(i\) 到第 \(j\) 个营地的总人数;

线段树的建立

引用自[这篇文章][(https://zhuanlan.zhihu.com/p/106118909)],写的挺好。

线段树是一棵 平衡二叉树。母结点代表整个区间的和,越往下区间越小。注意,线段树的每个 节点 都对应一条 线段(区间),但并不保证所有的线段(区间)都是线段树的节点,这两者应当区分开。

如果有一个数组[1,2,3,4,5],那么它对应的线段树大概长这个样子:

image

每个节点 p 的左右子节点的编号分别为 \(2p\) 和 \(2p+1\),假如节点 p 储存区间 [a,b] 的和,设 \(mid=(l+r)/2\),那么两个子节点分别储存 [l, mid] 和 [mid+1,r] 的和。可以发现,左节点对应的区间长度,与右节点相同或者比之恰好多1。


线段树的变换只能说是无穷无尽,根据题目的需求具体写法可能也不同,所以这只能在实战中联系了。

AC 代码:(打错一点就要调好久)

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int sum[N<<2],a[N];

void build(int l,int r,int rt){
	if(l==r){
		sum[rt]=a[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,rt*2);
	build(mid+1,r,rt*2+1);
	sum[rt]=sum[rt*2]+sum[rt*2+1];
}

void update(int p,int add,int l,int r,int rt){
	if(l==r){
		sum[rt]+=add;
		return;
	}
	int mid=(l+r)/2;
	if(p<=mid) update(p,add,l,mid,rt*2);
	else update(p,add,mid+1,r,rt*2+1);
	sum[rt]=sum[rt*2]+sum[rt*2+1]; 
}

int query(int cl,int cr,int l,int r,int rt){
	if(cl<=l&&r<=cr) return sum[rt];
	int mid=(l+r)/2;
	int ret=0;
	if(cl<=mid) ret+=query(cl,cr,l,mid,rt*2);
	if(cr>mid) ret+=query(cl,cr,mid+1,r,rt*2+1);
	return ret;
}

int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	build(1,n,1);
	while(m--){
		char ch[10];
		scanf("%s",ch+1);
		int i,j;
		scanf("%d%d",&i,&j);
		if(ch[1]=='Q') printf("%d\n",query(i,j,1,n,1));
		else if(ch[1]=='S') update(i,-j,1,n,1);
		else if(ch[1]=='A') update(i,j,1,n,1);
	}
	return 0;
}

标签:rt,正整数,int,线段,mid,算法,节点
From: https://www.cnblogs.com/alloverzyt/p/17741318.html

相关文章

  • 文心一言 VS 讯飞星火 VS chatgpt (105)-- 算法导论10.1 3题
    三、用go语言,仿照图10-2,画图表示依次执行操作ENQUEUE(Q,4)、ENQUEUE(Q,1)、ENQUEUE(Q,3)、DEQUEUE(Q)、ENQUEUE(Q,8)和DEQUEUE(Q)每一步的结果,队列初始为空,存储于数组Q[1..6]中。文心一言:在这个问题中,我们尝试使用Go语言来模拟队列的操作,并且展示每一步的结果。首先,我们需要定......
  • 文心一言 VS 讯飞星火 VS chatgpt (105)-- 算法导论10.1 3题
    三、用go语言,仿照图10-2,画图表示依次执行操作ENQUEUE(Q,4)、ENQUEUE(Q,1)、ENQUEUE(Q,3)、DEQUEUE(Q)、ENQUEUE(Q,8)和DEQUEUE(Q)每一步的结果,队列初始为空,存储于数组Q[1..6]中。文心一言:在这个问题中,我们尝试使用Go语言来模拟队列的操作,并且展示每一步的结果。首先,我们需要定义......
  • 记一种无需形式幂级数求逆的多点求值算法
    仅作为个人理解之用来自https://judge.yosupo.jp/submission/140699首先producttree部分不变我们考虑如何不使用形式幂级数求逆注意到如果对dft的点值求逆实际上是在对x^lim-1取模的意义下实际上在这个意义下也是可做的首先判掉所求点值在dft所用的单位根上的平凡情况(......
  • [数据结构和算法] 堆/优先队列的实现
    预备知识:完全二叉树可以用数组表示:从下标0开始存储数据:左子节点=2*父节点+1,右子节点=2*父节点+2;从下标1开始存储数据:左子结点=2*父节点,右子节点=2*父节点+1;堆:大根堆:父节点的值大于等于左右子节点的值;小根堆:父节点的值小于等于左右子节点的值;......
  • 线段树优化建图
    一个很好用的\(trick\)。我们通过例题CF786B为例。他需要我们支持点之间连边,点和区间之间连边,区间和点之间连边。支持最短路。如果我们暴力连边,显然最多是有\(n^2\)条边的。那怎么办呢,引入线段树分治。线段树分治在某些题中,我们可能会用\(v\tou\in[l,r]\)这种一个......
  • 文心一言 VS 讯飞星火 VS chatgpt (104)-- 算法导论10.1 2题
    二、用go语言,说明如何在一个数组A[1..n]中实现两个栈,使得当两个栈的元素个数之和不为n时,两者都不会发生上溢。要求PUSH和POP操作的运行时间为O(1)。文心一言:在这个问题中,我们要在一个数组A[1..n]中实现两个栈,使得当两个栈的元素个数之和不为n时,两者都不会发生上溢。这......
  • 文心一言 VS 讯飞星火 VS chatgpt (104)-- 算法导论10.1 2题
    二、用go语言,说明如何在一个数组A[1..n]中实现两个栈,使得当两个栈的元素个数之和不为n时,两者都不会发生上溢。要求PUSH和POP操作的运行时间为O(1)。文心一言:在这个问题中,我们要在一个数组A[1..n]中实现两个栈,使得当两个栈的元素个数之和不为n时,两者都不会发生上溢。......
  • 雷达到达角估计算法3DFFT,DBF,MUSIC,Capon的原理、对比、各自的优势
    雷达到达角估计算法3DFFT,DBF,MUSIC,Capon的原理、对比、各自的优势雷达到达角估计是雷达信号处理中的一个重要问题,旨在确定来自目标的雷达信号的到达角度。雷达到达角估计算法可以分为时域方法和频域方法两种类型。其中,频域方法可以进一步分为基于阵列信号处理的方法和基于普通雷达......
  • 选择排序算法:简单但有效的排序方法
    在计算机科学中,排序算法是基础且重要的主题之一。选择排序(SelectionSort)是其中一个简单但非常有用的排序算法。本文将详细介绍选择排序的原理和步骤,并提供Java语言的实现示例。选择排序的原理选择排序的核心思想是不断地从待排序的元素中选择最小的元素,然后将其放置在已排序部分的......
  • [算法]按位异或^的种种玩法
    本文使用C语言什么是按位异或^首先将不同数制的数写成二进制,例如9->0b1001.然后最末位对齐,依次按位异或.规则:0^0=0;1^1=0;1^0=1推论:任意整数x,都有0^x=x;x^x=0\来看看应用寻找一个单身狗数像[1,3,2,2,3]这样除了某一个数1,剩下的数字都是成......