/* 线段树学习:如果一个节点为i,那么他的左孩子为2I+1,右孩子为2i+2; */ #include<stdio.h> #define min(a,b) a<b?a:b; int tree[100]; int a[100] = {2,5,1,4,9,3}; //创建树 void create(int root, int c[], int start, int end) {//root表示当前线段树下标 //a表示用来构造线段树的数组 //star表示数组起始位置 //end表示数组末尾位置 if (start == end) { //叶子节点 tree[root] = c[start]; } else { int mid = (start + end) / 2; create(root * 2 + 1, a, start, mid);//构造左子树 create(root * 2 + 2, a, mid+1, end);//构造右子树 tree[root] = min(tree[root * 2 + 1], tree[root * 2 + 2]);//节点保存最小值 } } //线段树区间查询,查询最小值 int find(int root, int starti, int endi, int start, int end) { if (starti > end || endi < start) { return 65535;//无法查询到 } if (starti <=start&&endi >= end) { return tree[root]; } int mid = (start + end) / 2; return min(find(root * 2 + 1, starti, endi, start, mid),find(root*2+2,starti,endi,mid+1,end)); } //节点更新,节点的更新势必会影响到其父节点的更新,所以更新了节点之后还得更新其父节点 void update(int root, int start, int end, int index, int num) { //root表示树状数组根节点下标 //start区间其实下标 //end区间结尾下标 //index需要更新的结点在原数组中的的下标 //num更新的数值,假设加上num if (start == end) { //叶子节点 if (start == index) { //判断是否是需要跟新的结点 tree[root] += num; } } else { int mid = (start + end) / 2; if (index <= mid) { //二分,如果小于mid则只在左子树查找 update(root * 2 + 1, start, mid, index, num); } else { update(root * 2 + 2, mid + 1, end, index, num); } tree[root] = min(tree[root * 2 + 1], tree[root * 2 + 2]); } } int main() { create(0, a, 0,5); int x, y; int index, number; //情书如你要跟新的坐标和数值 scanf("%d %d", &index, &number); update(0, 0, 5, index, number); while (~scanf("%d %d", &x, &y)) { printf("%d ", find(0, x, y, 0,5)); } return 0; }