segTree

Segment Tree,又称区间树,是一种数据结构,用于高效地处理动态区间查询和更新问题。它通过将线性数组划分成多个连续子区间,并对每个子区间进行预处理,实现对区间元素的聚合操作(如求和、最大值、最小值等)以及修改操作。Segment Tree 结构通常用于解决在大型数据集上进行区间统计的问题,具有 O(logn) 的时间复杂度。
摘要由CSDN通过智能技术生成
#include<stido.h>
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define INF 0x7fffffff
#define size 100
int arr[size];
struct SegTreeNode
{
	int max;
	int min;
	int sum;
	int addMark;//延迟标记 
}segTree[4*size];//定义线段树 

/*
功能:构造线段树
root:当前线段树的根节点下标
arr:用来构造线段树的数组
istart:数组的起始位置
iend:数组的结束位置
*/ 
void build(int root,int istart,int iend,int arr[])
{
	segTree[root].addMark=0; 
	if(istart==iend)
		segTree[root].min=arr[istart];
	else{
		int mid=(istart+iend)/2;
		build(2*root+1,istart,mid,arr);//递归构造左子树 
		build(2*root+2,mid+1,iend,arr);//递归构造右子树
		//根据左右子树根节点的值,更新当前节点跟的值 
		segTree[root].min(segTree[2*root+1].min,segTree[2*root+2].min)
	}
}
 
/*
功能:当前节点的标志域指向孩子节点传递
root:当前线段树的根节点下标 
*/
void pushDown(int root)
{
	if(segTree[root].addMark!=0){
		//设置左右孩子的标志域,应为孩子节点可能被多次延迟标记又没有向下传递
		//所以是"+="
		segTree[2*root+1].addMark+=segTree[root].addMark;
		segTree[2*root+2].addMark+=segTree[root].addMark;
		//传递后,当前节点标记域清空
		segTree[root].addMark=0;
	}
} 


/*
功能:线段树区间查询
root:当前线段树的根节点下标
[nstart,nend]:当前节点所表示的区间
[qstart,qend]:此次查询区间 
*/
int query(int root,int nstart,int nend,int qstart,int qend)
{
	//查询区间和当前节点区间有没有交集 
	if(nend<qstart||nstart>qend)
		return INF;
	//当前节点区间包含在查询区间内 
	if(nstart>=qstart&&nend<=qend)
		return segTree[root].min;
	//分别从左右子树查询,返回两者查询结果的较小值 
	pushDown(root);
	int mid=(nstart+nend)/2;
	return min(query(2*root+1,nstart,mid,qstart,qend),query(2*root+2,mid+1,nend,qstart,qend));
}

/*
功能:更新线段树中某个叶子节点的值
root:当前线段树的根节点下标
[nstarat,nend]:当前节点所表示的区间
index:待更新节点在原始数组arr中的下标
addVal:更新的值(原来的值加上addVal) 
*/
void updateOne(int root,int nstart,int nend,int index,int addVal)
{
	if(nstart==nend){
		if(index==nstart)
			segTree[root].min+=addVal;//找到了相应的节点,更新之 
		return;
	}
	int mid=(nstart+nend)/2;
	if(int index<=mid)
		updateOne(2*root+1,nstart,mid,index,addVal);//在左子树中更新
	else updateOne(2*root+2,mid+1,nend,index,addVal);//在右子树中更新 
	//根据左右子树的值回溯更新当前节点的值 
	segTree[root].min=min(segTree[2*root+1].min,segTree[2*root+2].min);
} 

void update(int root,int nstart,int nend,int ustart,int uend,int addVal)
{
	//更新区间和当前节点区间没有交集 
	if(ustart>nend||uend<nstart)
		return;
	//当前节点区间包含在更新区间内
	if(ustart<=nstart&&uend>=nend){
		segTree[root].addMark+=addVal;
		segTree[root].min+=addVal; 
		return;
	}
	pushDown(root);
	//更新左右孩子节点
	int mid=(nstart+nend)/2;
	update(2*root+1,nstart,mid,ustart,uend,addVal);
	update(2*root+2,mid+1,nend,ustart,uend,addVal);
	//根据左右子树的值回溯更新当前节点的值
	segTree[root].min=min(segTree[2*root+1].min,segTree[2*root+2].min); 
}

int main()
{
	
	
	return 0;
}
void build(int root,int istart,int iend,int arr[])
{
	//addMark
	//叶子节点赋值 
	//不是叶子节点。先递归,再根据回溯的子节点赋值 
}
void pushDown(int root)
{
	//如果当前节点有标记
	//传给儿子
	//自己清掉 
} 

int query(int root,int nstart,int nend,int qstart,int qend);
{
	//当前节点区间与查询区间没有交集
	//当前节点区间在查询区间内 
	//先把标记传给儿子
	//到这里都没return,那肯定是不完全更新,根据更新的值重新计算
	//再递归回溯,根据两个儿子return
} 

void update(int root,int nstart,int nend,int ustart,int uend,int addVal)
{
	//当前节点表示区间和更新区间没有交集
	//当前节点表示区间在更新区间内
	//先把标记传给儿子
	//递归回溯,根据两个儿子的值来return 
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值