Line segment tree - point modification

Segment tree is a good thing
The line segment tree divides a large interval into some small intervals, which are used to find the maximum value of the interval. The more classic ones are seeking maximum and minimumThere are other weird things. Here is an example of finding the minimum value.

For convenience, the subscript of the line segment tree array is very metaphysical: for the current node number $o$, its left child node is numbered $2 o$, and its right child node is numbered $2 o+1$


Before closing and opening afterward, destroying the youthful closing interval is wonderful


  • First of all, you need a build, which can help you build a line segment tree relatively quickly, the code is as follows
    void build(int o,int l,int r){
        //o是当前节点编号,l和r是当前区间
        if(l==r){//遍历到了叶子节点
            minn[o]=a[l];//这个区间只有一个数,所以最小值也是这个数
            return;
        }
        int mid=(l+r)/2;//线段树的每个区间是对半分哒
        build(o*2,l,mid);//建左子树
        build(o*2+1,mid+1,r);//建右子树
        minn[o]=(minn[o*2],minn[o*2+1]);//回溯维护
    }
  • Then there is the update operation. Each time the value of a point is updated, the minimum value is maintained when backtracking. The code is as follows
    void update(int o,int l,int r,int x,int c){
        //o是当前节点编号,l和r是当前区间,x是要修改的位置,c是要修改成的值 
        if(l==r){//到要修改的点 
            minn[o]=c;
            return;
        }
        int mid=(l+r)/2;
        if(x<=mid) update(o*2,l,mid,x,c);//如果要修改的在左边的区间,修改左边的 
        else update(o*2+1,mid+1,r,x,c);// 如果要修改的在右边的区间,修改右边的
        //点修改没必要左右两边都递归下去,所以判一下在哪个区间,只修改那个区间就好啦 
        minn[o]=min(minn[o*2],minn[o*2+1]);//回溯维护最小值 
    }
  • There are also query operations. Query the minimum value in the range of a~b, the code is as follows

    int query(int a,int b,int o,int l,int r){
        //a,b是要查询的区间,o是当前节点的编号,l,r是当前的区间 
        if(a<=l&&b>=r) return minn[o];//当前的区间包含在要查询的区间内,返回 
        int mid=(l+r)/2;
        int qq=0x7fffffff;
        if(a<=mid) qq=min(qq,query(a,b,o*2,l,mid));//如果要查询的区间最左边的编号在当前查到区间的左半部分,那么要查询的区间肯定有一段在前查到区间的左半部分 
        if(b>mid) qq=min(qq,query(a,b,o*2+1,mid+1,r));//如果要查询的区间最右边的编号在当前查到区间的右半部分,那么要查询的区间肯定有一段在前查到区间的右半部分 
        //要注意的是,a,b这个要查询的区间是不变的,所以调用函数传值进去的时候不要传错了哦 
        return qq;//上面要查询的取个最小值,就是要求的啦 
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325384632&siteId=291194637