熱門文章

2026年5月24日 星期日

ZeroJudge 解題筆記:e457. 也是 Segment Tree 練習

作者:王一哲
日期:2026年5月24日


ZeroJudge 題目連結:e457. 也是 Segment Tree 練習

解題想法


單點修改,查詢區間連乘的正負號,不需要真的存數字,如果數字大於 0 存 1,等於 0 存 0,小於 0 存 -1。

Python 程式碼


使用時間約為 1.1 s,記憶體約為 33.9 MB,通過測試。
class SegmentTree:
    def __init__(self, data):
        self.n = len(data)
        self.data = [0]
        for d in data:
            if d > 0:
                self.data.append(1)
            elif d == 0:
                self.data.append(0)
            else:
                self.data.append(-1)
        self.tree = [0]*(4 * self.n)
        if self.n > 0:
            self._build(0, 1, self.n)
    
    # --- 內部遞迴函式 ---
    def _build(self, node, start, end):
        if start == end:
            if self.data[start] > 0:
                self.tree[node] = 1
            elif self.data[start] == 0:
                self.tree[node] = 0
            else:
                self.tree[node] = -1
            return

        mid = (end - start) // 2 + start
        self._build(2*node + 1, start, mid)
        self._build(2*node + 2, mid + 1, end)
        self.tree[node] = self.tree[2*node + 1] * self.tree[2*node + 2]

    def _update(self, node, start, end, target, val):
        if start == end:
            if val > 0:
                self.tree[node] = 1
                self.data[target] = 1
            elif val == 0:
                self.tree[node] = 0
                self.data[target] = 0
            else:
                self.tree[node] = -1
                self.data[target] = -1
            return

        mid = (end - start) // 2 + start
        if target <= mid:
            self._update(2*node + 1, start, mid, target, val)
        else:
            self._update(2*node + 2, mid + 1, end, target, val)
        self.tree[node] = self.tree[2*node + 1] * self.tree[2*node + 2]

    def _query(self, node, start, end, left, right):
        if end < left or start > right:
            return 1
        if left <= start and right >= end:
            return self.tree[node]
        mid = (end - start) // 2 + start
        lval = self._query(2*node + 1, start, mid, left, right)
        rval = self._query(2*node + 2, mid + 1, end, left, right)
        return lval * rval
    
    # --- 外部呼叫函式 ---
    def update(self, target, val):
        self._update(0, 1, self.n, target, val)

    def query(self, left, right):
        return self._query(0, 1, self.n, left, right)

def solve():
    import sys

    result = []
    data = sys.stdin.read().split()
    ptr = 0
    while ptr < len(data):
        n = int(data[ptr])
        k = int(data[ptr+1])
        ptr += 2
        nums = list(map(int, data[ptr:ptr+n]))
        ptr += n
        st = SegmentTree(nums)
        for i in range(k):
            op = data[ptr]
            x = int(data[ptr+1])
            y = int(data[ptr+2])
            ptr += 3
            if op == "C":
                st.update(x, y)
            else:
                z = st.query(x, y)
                if z == 1:
                    result.append("+")
                elif z == 0:
                    result.append("0")
                else:
                    result.append("-")
        result.append("\n")
    sys.stdout.write("".join(result))

if __name__ == "__main__":
    solve()


C++ 程式碼


使用時間約為 56 ms,記憶體約為 5 MB,通過測試。
#include <cstdio>
#include <vector>
using namespace std;

class SegmentTree {
private:
    int n;
    vector<int> data, tree;
    /* 內部遞迴函式 */
    void _build(int node, int start, int end) {
        if (start == end) {
            if (data[start] > 0) {  // 只存正1、負-1、零0
                tree[node] = 1;
            } else if (data[start] < 0) {
                tree[node] = -1;
            } else {
                tree[node] = 0;
            }
            return;
        }
        int mid = (end - start) / 2 + start;
        _build(2*node + 1, start, mid);
        _build(2*node + 2, mid + 1, end);
        tree[node] = tree[2*node + 1] * tree[2*node + 2];
    }

    void _update(int node, int start, int end, int target, int val) {
        if (start == end) {
            if (val > 0) {
                tree[node] = 1;
                data[target] = 1;
            } else if (val == 0) {
                tree[node] = 0;
                data[target] = 0;
            } else {
                tree[node] = -1;
                data[target] = -1;
            }
            return;
        }
        int mid = (end - start) / 2 + start;
        if (target <= mid) {
            _update(2*node + 1, start, mid, target, val);
        } else {
            _update(2*node + 2, mid + 1, end, target, val);
        }
        tree[node] = tree[2*node + 1] * tree[2*node + 2];
    }

    int _query(int node, int start, int end, int left, int right) {
        if (end < left || start > right) return 1;
        if (left <= start && right >= end) return tree[node];
        int mid = (end - start) / 2 + start;
        int lval = _query(2*node + 1, start, mid, left, right);
        int rval = _query(2*node + 2, mid + 1, end, left, right);
        return lval * rval;
    }

public:
    // 建構子
    SegmentTree(const vector<int>& input_data) {
        n = (int)input_data.size();
        data.resize(n+1);
        for(int i=0; i<n; i++) {
            if (input_data[i] > 0) data[i+1] = 1;
            else if (input_data[i] == 0) data[i+1] = 0;
            else data[i+1] = -1;
        }
        tree.assign(4*n, 0);  // 只存正1、負-1、零0
        if (n > 0) _build(0, 1, n);
    }
    /* 外部呼叫函式 */
    void update(int target, int val) {
        _update(0, 1, n, target, val);
    }

    int query(int left, int right) {
        return _query(0, 1, n, left, right);
    }
};

int main() {
    int n, k;
    while(scanf("%d %d", &n, &k) != EOF) {
        vector<int> input_data(n);
        for(int i=0; i<n; i++) {
            scanf("%d", &input_data[i]);
        }
        SegmentTree st(input_data);
        for(int i=0; i<k; i++) {
            char op;
            int x, y;
            scanf(" %c %d %d", &op, &x, &y);
            if (op == 'C') {
                st.update(x, y);
            } else {
                int z = st.query(x, y);
                if (z == 1) printf("+");
                else if (z == 0) printf("0");
                else printf("-");
            }
        }
        printf("\n");
    }
    return 0;
}


沒有留言:

張貼留言