线段树

概念:线段树将数组区间递归二分,每个结点维护一个区间信息,适用于区间求和、最值等可合并操作,并可扩展懒标记处理区间修改。

关键步骤

建树时叶子存数组值、父结点合并儿子;查询遇到完全覆盖直接返回,部分覆盖则递归两侧。单点修改沿根到叶的路径更新。

vector<long long> tr,a;
void build(int p,int l,int r){
    if(l==r){ tr[p]=a[l]; return; }
    int m=(l+r)/2; build(p*2,l,m); build(p*2+1,m+1,r);
    tr[p]=tr[p*2]+tr[p*2+1];
}
long long query(int p,int l,int r,int L,int R){
    if(L<=l && r<=R) return tr[p];
    int m=(l+r)/2; long long ans=0;
    if(L<=m) ans+=query(p*2,l,m,L,R);
    if(R>m) ans+=query(p*2+1,m+1,r,L,R); return ans;
}

复杂度

建树 O(n),单点更新与区间查询 O(log n),空间 O(n)(常开 4n)。区间更新需将懒标记下推后再访问子结点。