线段树 (Segment Tree)

高效处理区间查询与修改的数据结构

算法原理

线段树是一种二叉树结构,将数组分段存储,支持:

时间复杂度:查询和修改均为 $$ O(\log n) $$

线段树特点

  • 叶子节点对应数组中的单个元素
  • 内部节点存储对应区间的统计信息
  • 树高为 $$ \lceil \log_2 n \rceil $$
点击"构建线段树"开始

const int MAXN = 1 << 18;
int tree[MAXN * 4], a[MAXN];

// 建树
void build(int p, int l, int r) {
    if (l == r) {
        tree[p] = a[l];
        return;
    }
    int mid = (l + r) / 2;
    build(p * 2, l, mid);
    build(p * 2 + 1, mid + 1, r);
    tree[p] = tree[p * 2] + tree[p * 2 + 1];  // 区间和
}

// 区间查询
int query(int p, int l, int r, int ql, int qr) {
    if (ql <= l && r <= qr) return tree[p];
    if (qr < l || r < ql) return 0;  // 不相交
    int mid = (l + r) / 2;
    return query(p * 2, l, mid, ql, qr) +
           query(p * 2 + 1, mid + 1, r, ql, qr);
}

// 单点修改
void update(int p, int l, int r, int pos, int val) {
    if (l == r) {
        tree[p] = val;
        return;
    }
    int mid = (l + r) / 2;
    if (pos <= mid) update(p * 2, l, mid, pos, val);
    else update(p * 2 + 1, mid + 1, r, pos, val);
    tree[p] = tree[p * 2] + tree[p * 2 + 1];
}
                

应用场景

  • 区间求和:快速查询任意区间和
  • 区间最值:查询区间最大值/最小值
  • 动态统计:实时维护数据统计