線段樹

例題:node

https://www.luogu.org/problem/P3372(洛谷)ios

線段樹之單點更新:c++

模板:函數

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1E5+7; 
ll arr[N];
ll tree[N+N+N];
//若是咱們的tree從0開始,那麼左兒子爲2*node+1,右兒子爲2*node+2; 
//從1開始的話,左二子就是2*node,右兒子是2*node+1;
//在此咱們都從0開始; 
void buid_tree(ll node,ll start,ll end){//建樹 
    if(start==end){
        tree[node]=arr[end];
        return ;
    }
    ll mid=(start+end)>>1;
    ll left_node  =2*node+1;
    ll right_node =2*node+2;
    buid_tree(left_node ,start,mid);
    buid_tree(right_node,mid+1,end);
    tree[node]=tree[left_node]+tree[right_node];
}


void update_tree(ll node,ll start,ll end,ll idx,ll value){//節點更新 
    
    if(start==end) {
        arr[idx]+=value;
        tree[node]+=value;
        return ;
    }
    ll mid=(start+end) / 2 ;
    ll left_node=2*node+1;
    ll right_node=2*node+2;
    if(idx>=start && idx<=mid)    update_tree(left_node,start,mid,idx,value);
    else update_tree(right_node,mid+1,end,idx,value);
    tree[node]=tree[left_node]+tree[right_node];
}

ll  query_tree(ll node,ll start,ll end,ll l,ll r){//查詢函數 
    
    
    if(l>end||r<start) return 0;
    else if(l<=start&&end<=r) return tree[node];
    else if(start==end) return tree[node];
    
    
    
    ll mid=(start+end)/2;
    ll left_node=2*node+1;//左兒子 
    ll right_node=2*node+2;//右兒子 
    ll sum_left=query_tree(left_node,start,mid,l,r);
    ll sum_right=query_tree(right_node,mid+1,end,l,r);
    return sum_left+sum_right;
}

int main(){
    ios::sync_with_stdio(false);
    ll n,m;
    cin>>n>>m;
    for(ll i=0;i<n;i++) cin>>arr[i];
    buid_tree(0,0,n-1);
    for(ll i=1;i<=m;i++){
        ll t ;
        cin>>t;
        if(t==1){
            ll x,y,value;
            cin>>x>>y>>value;
            //因爲是單點更新,只能是一個點一個點的更新 
            for(ll j=x;j<=y;j++) update_tree(0,0,n-1,j-1,value);
        }
        
        else {
            ll  x,y;
            cin>>x>>y;
            x--,y--;
            cout<<query_tree(0,0,n-1,x,y)<<endl;
        }
    }
    return 0;
}
 

區間更新:ui

模板:spa

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=5E5+7;
ll arr[N];
//對於本題,咱們要用到區間更新,區間跟新與單點更新的區別之一就是區間更新用結構體,多了一個mark,用來標記
//某個節點是否須要跟新
//還有就是要在結構體中加l,r即當前節點維護的區間和,由於咱們是累加的當前節點的增長的數值應該是當前值乘以區間長度;(有的不是,
//具體狀況具體分析)
 
struct stu{
    ll l,r; 
    ll now;
    ll mark;
}tree[N];
void buid_tree(ll node,ll start,ll end){
    tree[node].mark=0;
    tree[node].l=start;
    tree[node].r=end;
    if(start==end){
        tree[node].now=arr[end];
        return ;
    }
    ll mid=(start+end)/2;
    ll left_node=2*node+1;
    ll right_node=2*node+2;
    buid_tree(left_node,start,mid);
    buid_tree(right_node,mid+1,end);
    tree[node].now=tree[left_node].now+tree[right_node].now;
}

void pushdown(ll root){
    ll left_node =root*2+1;
    ll right_node=root*2+2; 
    if(tree[root].mark!=0){
        tree[left_node].mark  +=tree[root].mark;
        tree[right_node].mark +=tree[root].mark;        
        tree[left_node].now   +=tree[root].mark*(tree[left_node].r-tree[left_node].l+1);
        tree[right_node].now  +=tree[root].mark*(tree[right_node].r-tree[right_node].l+1);
        tree[root].mark=0;
    }
}
void update_tree(ll node,ll start,ll end,ll l,ll r,ll value){
    if(end<l||start>r) return ;
    
    else if(start>=l&&end<=r) {
        tree[node].mark +=value;
        tree[node].now  +=value*(end-start+1);
        return ;
    }
    
    pushdown(node);//以當前節點爲根節點往下延伸 
    ll mid=(start+end) / 2;
    ll left_node=2*node+1;
    ll right_node=2*node+2;
    
    update_tree(left_node,start,mid,l,r,value);
    update_tree(right_node,mid+1,end,l,r,value);    
    tree[node].now=tree[left_node].now+tree[right_node].now;    
}


ll query_tree(ll node,ll start,ll end,ll l,ll r){
    
    
    if(end<l||start>r) return 0;
    else if(start>=l&&end<=r) return tree[node].now;
    
    pushdown(node);//延伸處理; 
    ll mid=(start+end)/2;
    ll left_node=2*node+1;
    ll right_node=2*node+2;
    ll sum_left=query_tree(left_node,start,mid,l,r);
    ll sum_right=query_tree(right_node,mid+1,end,l,r);
    return sum_left+sum_right;
}
int main(){
    memset(tree,0,sizeof tree);
    ll n,m;
    cin>>n>>m;
    for(ll i=0;i<n;i++)    cin>>arr[i];
    
    buid_tree(0,0,n-1);    
    for(ll i=0;i<m;i++){
        ll t;
        cin>>t;
        if(t==1){
            ll l,r,value;
            cin>>l>>r>>value;
            l--,r--;
            update_tree(0,0,n-1,l,r,value);
        }
        else{
            ll x,y;
            cin>>x>>y;
            x--,y--;
            cout<<query_tree(0,0,n-1,x,y)<<endl;
        }
    }
    return 0;
}
相關文章
相關標籤/搜索