2 条题解

  • 2
    @ 2024-03-17 11:13:12

    根据9Cirno的题解重写一个Python实现的SegmentTree

    class SegmentTree:
        tree = dict()
        lazy = dict()
        a = None
    
        def __init__(self, a):
            self.a = a
    
        def ls(self, p):
            return p << 1
    
        def rs(self, p):
            return p << 1 | 1
    
        def push_up(self, p):
            self.tree[p] = self.tree[self.ls(p)] + self.tree[self.rs(p)]
        
        def build(self, p, l, r):
            if l == r:
                self.tree[p] = self.a[l]
                return
            m = (l + r) >> 1
            self.build(self.ls(p), l, m)
            self.build(self.rs(p), m + 1, r)
            self.push_up(p)
        
        def add_lazy(self, p, l, r, k):
            self.tree[p] += k * (r - l + 1)
            if self.lazy.get(p, 0) == 0:
                self.lazy[p] = k
            else:
                self.lazy[p] += k
        
        def push_down(self, p, l, r):
            if self.lazy.get(p, 0) == 0:
                return
            m = (l + r) >> 1
            self.add_lazy(self.ls(p), l, m, self.lazy[p])
            self.add_lazy(self.rs(p), m + 1, r, self.lazy[p])
            self.lazy[p] = 0
        
        def update(self, L, R, p, l, r, k):
            if L <= l and r <= R:
                self.add_lazy(p, l, r, k)
                return
            self.push_down(p, l, r)
            m = (l + r) >> 1
            if L <= m:
                self.update(L, R, self.ls(p), l, m, k)
            if R > m:
                self.update(L, R, self.rs(p), m + 1, r, k)
            self.push_up(p)
        
        def query(self, L, R, p, l, r):
            if L <= l and r <= R:
                return self.tree[p]
            self.push_down(p, l, r)
            m = (l + r) >> 1
            res = 0
            if L <= m:
                res += self.query(L, R, self.ls(p), l, m)
            if R > m:
                res += self.query(L, R, self.rs(p), m + 1, r)
            return res
    
    if __name__ == "__main__":
        n, m = map(int, input().strip().split())
        a = list(map(int, input().strip().split()))
        a.insert(0, 0) # 不使用0号位
        st = SegmentTree(a)
        st.build(1, 1, n)
        for _ in range(m):
            ipt = input().strip().split()
            if len(ipt) == 4:
                x, y, k = map(int, ipt[1:])
                st.update(x, y, 1, 1, n, k)
            else:
                x, y = map(int, ipt[1:])
                ans = st.query(x, y, 1, 1, n)
                print(ans, (ans << 1) + (ans << 2))
    

    如果需要实现其他的维护,您需要自定义类继承SegmentTree类,并重写add_lazy方法

  • 2
    @ 2024-03-13 20:21:06

    省流:线段树板子

    #include <iostream>
    using namespace std;
    typedef long long ll;
    const int N = 100010;
    
    struct segment_tree {
    private:
        void add(ll k) {
            laz += k;
            sum += k * (r - l + 1);
        }
        
        void push_down() {
            if (laz) {
                ls->add(laz);
                rs->add(laz);
                laz = 0;
            }
        }
        
    public:
        ll l, r;
        ll sum, laz;
        segment_tree *ls, *rs;
        
        void push_up() {
            sum = ls->sum + rs->sum;
        }
        
        void update(int L, int R, int k) {
            if (L <= l && R >= r) {
                add(k);
                return;
            }
            push_down();
            if (L <= ls->r) ls->update(L, R, k);
            if (R >= rs->l) rs->update(L, R, k);
            push_up();
        }
        
        ll query(ll L, ll R) {
            if (L <= l && R >= r) return sum;
            push_down();
            ll res = 0;
            if (L <= ls->r) res += ls->query(L, R);
            if (R >= rs->l) res += rs->query(L, R);
            return res;
        }
    } tree[N << 2], *pos = tree;
    
    ll a[N];
    
    segment_tree *build(ll l, ll r) {
        auto tmp = pos++;
        tmp->l = l, tmp->r = r;
        if (l != r) {
            ll mid = (l + r) >> 1;
            tmp->ls = build(l, mid);
            tmp->rs = build(mid + 1, r);
            tmp->push_up();
        } else tmp->sum = a[l];
        return tmp;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr), cout.tie(nullptr);
        
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; i++) cin >> a[i];
        auto rt = build(1, n);
        
        while (m--) {
            int op, l, r, k;
            cin >> op;
            if (op == 1) {
                cin >> l >> r >> k;
                rt->update(l, r, k);
            } else {
                cin >> l >> r;
                ll ans = rt->query(l, r);
                cout << ans << ' ' << (ans << 1) + (ans << 2) << '\n';
            }
        }
        return 0;
    }
    
  • 1

原始人,启动 / 【模板】线段树

信息

ID
1047
难度
9
分类
线段树 点击显示
标签
递交数
9
已通过
3
通过率
33%
被复制
1
上传者