一维动态差分(区修单查)

一维动态差分(区修单查)

动态差分是差分数组的动态实现,通过树状数组维护差分数组,可以在 的时间复杂度内完成区间修改和单点查询操作。

基本概念

动态差分的核心思想是:

  1. 使用树状数组维护差分数组
  2. 区间修改转化为差分数组的两点修改
  3. 单点查询通过前缀和实现
  4. 适用于区间修改和单点查询交替的场景

实现方式

动态差分的关键操作:

  1. update:修改差分数组某个位置的值
  2. query:查询差分数组的前缀和
  3. rangeAdd:区间增加操作
  4. pointQuery:单点查询

基本实现

class DynamicDifference {
private:
    vector<int> tree;
    int n;
    
    int lowbit(int x) {
        return x & (-x);
    }
    
    void update(int idx, int val) {
        while (idx <= n) {
            tree[idx] += val;
            idx += lowbit(idx);
        }
    }
    
    int query(int idx) {
        int sum = 0;
        while (idx > 0) {
            sum += tree[idx];
            idx -= lowbit(idx);
        }
        return sum;
    }

public:
    DynamicDifference(int size) : n(size) {
        tree.resize(n + 1);
    }
    
    // 区间[left, right]增加val
    void rangeAdd(int left, int right, int val) {
        update(left + 1, val);
        update(right + 2, -val);
    }
    
    // 查询位置idx的值
    int pointQuery(int idx) {
        return query(idx + 1);
    }
};
class DynamicDifference {
    private int[] tree;
    private int n;
    
    public DynamicDifference(int size) {
        n = size;
        tree = new int[n + 1];
    }
    
    private int lowbit(int x) {
        return x & (-x);
    }
    
    private void update(int idx, int val) {
        while (idx <= n) {
            tree[idx] += val;
            idx += lowbit(idx);
        }
    }
    
    private int query(int idx) {
        int sum = 0;
        while (idx > 0) {
            sum += tree[idx];
            idx -= lowbit(idx);
        }
        return sum;
    }
    
    // 区间[left, right]增加val
    public void rangeAdd(int left, int right, int val) {
        update(left + 1, val);
        update(right + 2, -val);
    }
    
    // 查询位置idx的值
    public int pointQuery(int idx) {
        return query(idx + 1);
    }
}
class DynamicDifference:
    def __init__(self, size):
        self.n = size
        self.tree = [0] * (size + 1)
    
    def lowbit(self, x):
        return x & (-x)
    
    def update(self, idx, val):
        while idx <= self.n:
            self.tree[idx] += val
            idx += self.lowbit(idx)
    
    def query(self, idx):
        total = 0
        while idx > 0:
            total += self.tree[idx]
            idx -= self.lowbit(idx)
        return total
    
    # 区间[left, right]增加val
    def range_add(self, left, right, val):
        self.update(left + 1, val)
        self.update(right + 2, -val)
    
    # 查询位置idx的值
    def point_query(self, idx):
        return self.query(idx + 1)

应用场景

动态差分在很多问题中都有应用:

  1. 动态区间增减
  2. 实时流量统计
  3. 在线温度变化
  4. 动态人流量统计
  5. 实时区间修改

示例:区间加法

class Solution {
private:
    DynamicDifference* dd;
    
public:
    vector<int> getModifiedArray(int length, vector<vector<int>>& updates) {
        dd = new DynamicDifference(length);
        
        // 执行所有更新操作
        for (const auto& update : updates) {
            int start = update[0];
            int end = update[1];
            int val = update[2];
            dd->rangeAdd(start, end, val);
        }
        
        // 查询每个位置的值
        vector<int> result(length);
        for (int i = 0; i < length; i++) {
            result[i] = dd->pointQuery(i);
        }
        
        return result;
    }
};
class Solution {
    private DynamicDifference dd;
    
    public int[] getModifiedArray(int length, int[][] updates) {
        dd = new DynamicDifference(length);
        
        // 执行所有更新操作
        for (int[] update : updates) {
            int start = update[0];
            int end = update[1];
            int val = update[2];
            dd.rangeAdd(start, end, val);
        }
        
        // 查询每个位置的值
        int[] result = new int[length];
        for (int i = 0; i < length; i++) {
            result[i] = dd.pointQuery(i);
        }
        
        return result;
    }
}
class Solution:
    def getModifiedArray(self, length: int, updates: List[List[int]]) -> List[int]:
        dd = DynamicDifference(length)
        
        # 执行所有更新操作
        for start, end, val in updates:
            dd.range_add(start, end, val)
        
        # 查询每个位置的值
        result = []
        for i in range(length):
            result.append(dd.point_query(i))
        
        return result

时间复杂度

  • 初始化:
  • 区间修改:
  • 单点查询:
  • 空间复杂度:

动态差分 vs 静态差分

优点:

  1. 支持动态操作
  2. 单点查询更快
  3. 无需还原整个数组

缺点:

  1. 实现较复杂
  2. 常数较大
  3. 内存占用略多

注意事项

  1. 树状数组下标从1开始
  2. 区间修改的边界处理
  3. 注意差分数组的范围
  4. 处理负数和溢出

练习建议

  1. 实现基本的动态差分
  2. 解决区间修改问题
  3. 比较静态和动态实现
  4. 尝试扩展到二维
牛客代码笔记-牛栋 文章被收录于专栏

汗牛充栋,学海无涯。<br/> 内含算法知识点讲解,以及牛客题库精选例题。<br/> 学习算法,从牛栋开始。

全部评论

相关推荐

我知道自己这个念头不好,但是真的很羡慕😭大家的父母长辈都能帮到自己吗?
大飞的诡术妖姬:父母都是普通打工人,身体也不好,能供我读到本科毕业很不容易,毕业以后帮衬心里会有罪恶感。虽然可能会错过很多风景,但还是想活的心安理得。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务