zoukankan      html  css  js  c++  java
  • 线段树学习笔记

        之前就已经学过了,放在了本地,现在搬到博客园来~

         关于线段树的视频学习,强烈推荐B站此大佬的讲解:https://www.bilibili.com/video/BV1cb411t7AM

         1.概念:线段树是一种二叉搜索树,与区间树相似。线段树是建立在线段或区间基础上的树,树的每个结点代表一条线段[L,R]。

        2:根据视频里的内容,我做出了这张图。arr[]数组,求它区间和,以及对它进行某些数的修改

         根据此,有build_tree:

    void build_tree(int node,int start,int end)
    {
        if(start==end)
        {
            tree[node]=arr[start];
        }
        else
        {
            int mid=(start+end)/2;
            int left_node=node*2+1;
            int right_node=node*2+2;
            build_tree(left_node,start,mid);
            build_tree(right_node,mid+1,end);
            tree[node]=tree[left_node]+tree[right_node];
        }
    }

        对于update,需要修改arr[]的某个数,改变最下面的start==end的结点,那么上面跟它有关系的结点都要进行更新。start==end依然是作为递归的出口。看idx的位置,在左孩子里就更新左孩子,否则右孩子。

    void update_tree(int node,int start,int end,int idx,int val)
    {
        if(start==end)
        {
            tree[node]=val;
            arr[idx]=val;
        }
        else
        {
            int mid=(start+end)/2;
            int left_node=node*2+1;
            int right_node=node*2+2;
            if(idx>=start&&idx<=mid)
                update_tree(left_node,start,mid,idx,val);
            else
                update_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(l<=start&&end<=r)  
        {
            return tree[node];
        }
        else if(start==end)
        {
            return tree[node];
        }
        else
        {
            int mid=(start+end)/2;
            int left_node=node*2+1;
            int right_node=node*2+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;
        }
    
    }

        总的代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=1000;
    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=node*2+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(l<=start&&end<=r)
        {
            return tree[node];
        }
        else if(start==end)
        {
            return tree[node];
        }
        else
        {
            int mid=(start+end)/2;
            int left_node=node*2+1;
            int right_node=node*2+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;
        }
    
    }
    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);
        for(int i=0;i<15;i++)
            cout<<tree[i]<<" ";
            cout<<endl;
        update_tree(arr,tree,0,0,size-1,4,6);
        for(int i=0;i<15;i++)
            cout<<tree[i]<<" ";
            cout<<endl;
        cout<<query_tree(arr,tree,0,0,size-1,2,4);
    }
  • 相关阅读:
    iOS 获取系统通知开关状态[隐式推送]
    iOS collectionView自适应高度estimatedItemSize
    iOS 审核被拒:2.1 App Tracking Transparency permission request
    大小端
    注解@Mapper(componentModel = "spring")自动生成DTODO的模型映射
    Nexus3_windows部署及Nuget上传
    Winform_打包_CEF
    Nexus3_windows部署及NPM上传
    生成url的二维码图片
    微信小程序实现图片是上传、预览功能
  • 原文地址:https://www.cnblogs.com/liyexin/p/12682041.html
Copyright © 2011-2022 走看看