灯神视频讲解线段树
【题目】给定一个数组arr,数组可能非常大。在程序运行过程中,你可能要做好几次query和update操作:
1.query(arr, L, R) 表示计算数组arr中,从下标L到下标R之间的所有数字的和。
2.update(arr, i, val) 表示要把arr[i]中的数字改成val。

#include<cstdio>
const int maxn = 1e3+5;
//建树 
void build_tree(int arr[], int tree[], int node, int start, int end){
	if(start == end){
		tree[node] = arr[start]; //这里是tree[node]注意别写错了 
	}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(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(arr, tree, left_node, start, mid, idx, val);
		}else{
			update(arr, tree, right_node, mid+1, end, idx, val);
		}
		tree[node] = tree[left_node] + tree[right_node];
	}
}
//查询
int query(int arr[], int tree[], int node, int start, int end, int L, int R){
	if(R < start || L > end) return 0;
	else if(L<=start && R<= end) return tree[node];
	else if(start == end) 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(arr, tree, left_node, start, mid, L, R);
		int sum_right = query(arr, tree, right_node, mid+1, end, L, R);
		return sum_left + sum_right;
	}
} 
int main(){
	int arr[]={1,3,5,7,9,11};
	int size = 6;
	int tree[maxn]={0};
	build_tree(arr, tree, 0, 0, size-1);
	update(arr, tree, 0, 0, size-1, 4, 6);
	for(int i=0;i<15;i++){
		printf("tree[%d]=%d\n",i, tree[i]);
	}
	int s= query(arr, tree, 0, 0, size-1, 2, 5);
	printf("%d\n", s);
	return 0;
}