线段树(Segment Tree)

手写相关函数,在这总结一下。

 

建立线段树

void build_tree(int arr[],int tree[],int node,int start,int end){

	if(start==end){
		tree[node] = arr[start];//叶子节点
	}
	else{
		int mid = (start + end)/2;
		int left_node = 2*node + 1;
		int right_node = 2*node + 2;
		build_tree( arr, tree, left_node, start, mid);//递归建左子树
		build_tree( arr, tree, right_node, mid+1, end);//递归建右子树
		tree[node] = tree[left_node] + tree[right_node];//维护
	}
}
         

 

更新某元素

void update_tree(int arr[],int tree[],int node, int start, int end,int idx, int val){
	 
	 if(start == end){
	 	arr[idx] = val;
	 	tree[node] = val;
	 }
	 
	 else{
	 	int mid = (start + end)/2;
	 	int left_node = 2*node +1;
	 	int right_node = 2*node +2;
	 	if(idx >= start &&idx <= mid){
	 		update_tree( arr, tree, left_node, start, mid, idx, val);
	 	}
	 	else{
	 		update_tree( arr, tree, right_node, mid+1, end, idx, val);
	 	}
	 	tree[node] = tree[left_node]+tree[right_node];
	}
}

  

 

查询区间和

int query_tree(int arr[], int tree[], int node, int start, int end, int L, int R){
	if(R<start||L>end){
		return 0;
	}else if(start == end||start>=L&&end<=R){//这里如果没有后面的,则每次查询都会一直递归到叶子节点,降低效率
		return tree[node];
	}
	else{
	
	
		int mid = (start+end)/2;
		int left_node = 2*node + 1;
		int right_node = 2*node+2;
		int sum_left = query_tree( arr, tree, left_node, start, mid, L, R);
		int sum_right = query_tree( arr, tree, right_node, mid+1, end, L, R);
		return sum_left+sum_right;
	}

 

区间操作(加法)

void plus_tree(int arr[],int tree[],ll node,ll start,ll end,ll L,ll R,ll num){
	if(start == end){
		tree[node] += num;
	}
	else {
		int mid = (start+end)/2;
		int left_node = 2*node+1;
		int right_node = 2*node+2;
		if(L<=mid){
			plus_tree(arr, tree, left_node, start, mid, L, R, num);
		}
		if (R>=mid+1){
			plus_tree(arr, tree, right_node, mid+1, end, L, R, num);
		}
		
		tree[node] = tree[left_node]+tree[right_node];
	}
}

  

 

 

 

posted @ 2020-01-18 23:33  LeoRanbom  阅读(223)  评论(0编辑  收藏  举报