Solution

class Solution:
    def getNumber(self, root: Optional[TreeNode], ops: List[List[int]]) -> int:
        self.arr = []
        def traverse(r):
            if not r:
                return
            traverse(r.left)
            self.arr.append(r.val)
            traverse(r.right)
        traverse(root)
        def find_bound(x, y):
            # x <= arr[left...right] <= y   1 3 4 4 6 8
            left = bisect_left(self.arr, x)
            right = bisect_right(self.arr, y) - 1
            return left, right
        res = 0
        for t, x, y in ops[::-1]:  # 每个节点的最终颜色取决于最后一次染色
            left, right = find_bound(x, y)
            if t == 1:
                res += right + 1 - left
            self.arr =  self.arr[:left] + self.arr[right+1:]  # 去掉染过色的节点
        
        return res

线段树的解法

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

 //[769836168,10709914,986872749,null,569945181,850182753,null,514412027,691018511,842990509,886343010,128384490,null,582871641,756062719,null,null,null,null,51807103,514127439,null,590845769,744651324,null,null,null,251214860,null,null,665257777,null,null,222643485,431635363,null,null,null,null,290988646]
// [[1,514127439,769836168],[0,756062719,850182753],[1,290988646,590845769],[0,756062719,886343010],[0,51807103,290988646],[1,691018511,691018511],[0,290988646,842990509],[0,590845769,665257777],[1,665257777,756062719],[1,590845769,769836168],[1,744651324,744651324],[1,590845769,756062719],[1,290988646,590845769],[1,769836168,986872749],[0,582871641,850182753],[1,665257777,665257777],[0,514127439,756062719],[1,842990509,842990509],[0,850182753,986872749]]

class Solution {
    public int getNumber(TreeNode root, int[][] ops) {
        List<Integer> list = new ArrayList<>();
        dfs(root, list);
        int[] nums = new int[list.size()];
        for (int i = 0; i < nums.length; i++) {
            nums[i] = list.get(i);
            // System.out.print("" + nums[i] + ", ");
        }
        // System.out.println();
        int[] diff = new int[nums.length];
        SegmentTree st = new SegmentTree(diff);
        for (int[] op : ops) {
            int c = op[0];
            int x = op[1], y = op[2];
            if (x > nums[nums.length - 1] || y < nums[0]) continue;
            // find x pos
            int left = 0, right = nums.length - 1;
            while (left < right) {
                int mid = left + (right - left) / 2;
                if (nums[mid] >= x) right = mid;
                else left = mid + 1;
            }
            int tx = left;
            // find y pos
            left = 0; right = nums.length - 1;
            while (left < right) {
                int mid = left + (right - left + 1) / 2;
                if (nums[mid] <= y) {
                    left = mid;
                } else {
                    right = mid - 1;
                }
            }
            int ty = left;
            if (tx > ty) continue;
            st.update(tx, ty, c);
            // st.query(0, diff.length - 1);
            // System.out.println(st.query(0, diff.length - 1) + " # " + c + " # " + "[" + tx + ", " + ty + "]" + " # " + "[" + x + ", " + y + "]");
        }
        return st.query(0, diff.length - 1);
        
    }
    
    void dfs(TreeNode root, List<Integer> list) {
        if (root == null) return;
        dfs(root.left, list);
        list.add(root.val);
        dfs(root.right, list);
    }
}

class SegmentTree {
    private int[] tree, nums, lazy;
    final int INIT = -1;
    public SegmentTree(int[] nums) {
        int n = nums.length;
        tree = new int[4*n];
        lazy = new int[4*n];    // lazy tag
        Arrays.fill(lazy, INIT);
        this.nums = nums;
        buildTree(0, 0, n-1);
    }

    private void buildTree(int node, int start, int end) {
        if (start == end) {
            tree[node] = nums[start];
            return;
        }
        int mid = start + (end - start) / 2;
        int leftNode  = node * 2 + 1;
        int rightNode = node * 2 + 2;

        buildTree(leftNode, start, mid);
        buildTree(rightNode, mid+1, end);

        tree[node] = tree[leftNode] + tree[rightNode];
    }

    private void pushDown(int node, int start, int end) {
        if (lazy[node] == INIT) {
            return;
        }
        int leftNode = node * 2 + 1;
        int rightNode = node * 2 + 2;
        int mid = start + (end - start) / 2;
        
        // 如果方案为区间增值,把下面四个 = 改成 += 即可
        tree[leftNode] = lazy[node] * (mid - start + 1);
        lazy[leftNode] = lazy[node];
        tree[rightNode] = lazy[node] * (end - mid);
        lazy[rightNode] = lazy[node];
        // 清空当前 lazy tag
        lazy[node] = INIT;
    }

    private void updateTree(int node, int start, int end, int left, int right, int val) {
        // 当前节点被区间完全覆盖,更新节点并设置 lazy tag,这样就没必要向下更新了
        if (left <= start && end <= right) {
            // 如果方案为区间增值,把下面两个 = 改成 += 即可
            tree[node] = (end - start + 1) * val;  
            lazy[node] = val;   
            return;
        }

        // 把当前节点的 lazy tag 传递到下一层
        pushDown(node, start, end);

        int mid = start + (end - start) / 2;
        int leftNode = 2 * node + 1;
        int rightNode = 2 * node + 2;

        // 需要更新左子树
        if (left <= mid) {
            updateTree(leftNode, start, mid, left, right, val);
        } 
        // 需要更新右子树
        if (right > mid) {
            updateTree(rightNode, mid+1, end, left, right, val);
        } 
        // 更新当前节点
        tree[node] = tree[leftNode] + tree[rightNode];
    }

    private int queryTree(int node, int start, int end, int left, int right) {
        // 查找范围不在当前范围内
        if (right < start || left > end) {
            return 0;
        }
        // 当前范围就在查找范围中,直接返回
        if (start >= left && end <= right) {
            return tree[node];
        }
        
        // 部分范围在查找区间中,先把 lazy tag 传下去
        pushDown(node, start, end);
        

        int mid = start + (end - start) / 2;
        int leftNode = 2 * node + 1;
        int rightNode = 2 * node + 2;
        int leftSum = queryTree(leftNode, start, mid, left, right);
        int rightSum = queryTree(rightNode, mid+1, end, left, right);
        return leftSum + rightSum;
    }

    public void update(int index, int val) {
        updateTree(0, 0, nums.length-1, index, index, val); 
    }

    public void update(int left, int right, int val) {
        updateTree(0, 0, nums.length - 1, left, right, val);
    }
    
    public int query(int left, int right) {
        int result = queryTree(0, 0, nums.length-1, left, right);
        return result;
    }
}

使用模板Range

力扣

class Solution {
public:
    int dfs(TreeNode* root, RangeModule& s) {
        return root ? s.queryRange(root->val, root->val + 1) + dfs(root->left, s) + dfs(root->right, s) : 0;
    }
    
    int getNumber(TreeNode* root, vector<vector<int>>& ops) {
        RangeModule s;
        for (const auto& e : ops) {
            switch (e[0]) {
                case 0:s.removeRange(e[1], e[2] + 1);break;
                case 1:s.addRange(e[1], e[2] + 1);break;
            }
        }
        return dfs(root, s);
    }
};

作者:vclip
链接:<https://leetcode-cn.com/problems/QO5KpG/solution/yong-by-vclip-pgc1/>
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class RangeModule(object):
    def __init__(self):
        self.ranges = []

    def _bounds(self, left, right):
        i, j = 0, len(self.ranges) - 1
        for d in (100, 10, 1):
            while i + d - 1 < len(self.ranges) and self.ranges[i+d-1][1] < left:
                i += d
            while j >= d - 1 and self.ranges[j-d+1][0] > right:
                j -= d
        return i, j

    def addRange(self, left, right):
        i, j = self._bounds(left, right)
        if i <= j:
            left = min(left, self.ranges[i][0])
            right = max(right, self.ranges[j][1])
        self.ranges[i:j+1] = [(left, right)]

    def queryRange(self, left, right):
        i = bisect.bisect_left(self.ranges, (left, float('inf')))
        if i: i -= 1
        return (bool(self.ranges) and
                self.ranges[i][0] <= left and
                right <= self.ranges[i][1])

    def removeRange(self, left, right):
        i, j = self._bounds(left, right)
        merge = []
        for k in xrange(i, j+1):
            if self.ranges[k][0] < left:
                merge.append((self.ranges[k][0], left))
            if right < self.ranges[k][1]:
                merge.append((right, self.ranges[k][1]))
        self.ranges[i:j+1] = merge

作者:LeetCode
链接:<https://leetcode-cn.com/problems/range-module/solution/range-mo-kuai-by-leetcode/>
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。