线段树

对一个数组,如果要同时进行多次求区间和操作,修改元素操作。怎样能使时间复杂度降到最低?线段树为我们解决了这样一个问题。

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
const int N=1010;
int tree[N],arr[N];
//建立一颗完全二叉树
void build_tree(int arr[], int tree[], int node, int st, int ed){
    if(st==ed){
        tree[node]=arr[st];
    }else{
        int mid=st+ed>>1;
        int l_node=2*node+1;
        int r_node=2*node+2;
        build_tree(arr,tree,l_node, st, mid);
        build_tree(arr,tree,r_node,mid+1,ed);
        tree[node]=tree[l_node]+tree[r_node];
    }
}
//更新数组中某一个下标的值
void update_arr(int arr[], int tree[], int node, int st, int ed, int idx, int val){
    if(st==ed){
        arr[idx]=val;
        tree[node]=val;
    }else{
        int mid=st+ed>>1;
        int l_node=2*node+1;
        int r_node=2*node+2;
        if(idx>=st&&idx<=mid){
            update_arr(arr,tree,l_node,st,mid,idx,val);
        }else{
            update_arr(arr,tree,r_node,mid+1,ed,idx,val);
        }
        tree[node]=tree[l_node]+tree[r_node];
    }
}
//计算arr中区间[L,R]的和
int query_arr(int arr[], int tree[],int node, int st, int ed, int L, int R){
    if(R<st||L>ed){
        return 0;
    }else if(L<=st&&ed<<R){
        return tree[node];
    }else if(st==ed){
        return tree[node];
    }else{
        int mid=st+ed>>1;
        int l_node=2*node+1;
        int r_node=2*node+2;
        int sum_l=query_arr(arr,tree,l_node,st,mid,L,R);
        int sum_r=query_arr(arr,tree,r_node,mid+1,ed,L,R);
        return sum_l+sum_r;
    }

}
int main(void){
    int n;
    cin>>n;
    for(int i=0;i<n;i++)cin>>arr[i];
    build_tree(arr,tree,0,0,n-1);
    for(int i=0;i<15;i++)cout<<tree[i]<<' ';
    update_arr(arr,tree,0,0,n-1,4,6);//修改a[4]=6;
    cout<<tree[0]<<endl;
    return 0;
}

 

posted @ 2019-07-31 17:04  YF-1994  阅读(158)  评论(0编辑  收藏  举报