线段树学习----C语言

/*
    线段树学习:如果一个节点为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;
}
原文地址:https://www.cnblogs.com/lin0/p/8612605.html