BIT-Count of Range Sum
阅读原文时间:2023年07月08日阅读:2

2019-12-17 18:56:56

问题描述

问题求解

本题个人感觉还是很有难度的,主要的难点在于如何将题目转化为bit计数问题。

首先构建一个presum数组,这个没有问题。

需要对于任意一个j,我们需要知道的是presum[i]的个数使得 lower <= presum[j] - presum[i] <= upper。

上述等式等价于求符合 presum[j] - upper <= presum[i] <= presum[j] - lower 的presum[i]的个数。

看到这个是不是有点眼熟了呢,求满足某个条件的区间的个数,这个和逆序数问题是完全一致的,只是在那个问题里我们只有一个上界,这里多了一个下界罢了。

同逆序数的解法,这里我们可以使用树状数组来进行求解。

public int countRangeSum(int\[\] nums, int lower, int upper) {  
    if (nums.length == 0) return 0;  
    int res = 0;  
    int n = nums.length;  
    long\[\] presum = new long\[n\];  
    presum \[0\] = nums\[0\];  
    for (int i = 1; i < n; i++) presum\[i\] = presum\[i - 1\] + nums\[i\];  
    long\[\] copy = Arrays.copyOf(presum, n);  
    Arrays.sort(copy);  
    TreeMap<Long, Integer> map = new TreeMap<>();  
    int rank = 0;  
    for (int i = 0; i < n; i++) {  
        if (i == 0 || copy\[i\] != copy\[i - 1\]) {  
            map.put(copy\[i\], ++rank);  
        }  
    }  
    int\[\] bit = new int\[map.size() + 1\];  
    for (int i = 0; i < n; i++) {  
        if (presum\[i\] >= lower && presum\[i\] <= upper) res += 1;  
        Long r = map.floorKey(presum\[i\] - lower);  
        Long l = map.ceilingKey(presum\[i\] - upper);  
        if (l != null && r != null) res += query(bit, map.get(r)) - query(bit, map.get(l) - 1);  
        update(bit, map.get(presum\[i\]));  
    }  
    return res;  
}

private void update(int\[\] bit, int idx) {  
    for (int i = idx; i < bit.length; i += i & -i) {  
        bit\[i\] += 1;  
    }  
}

private int query(int\[\] bit, int idx) {  
    int res = 0;  
    for (int i = idx; i > 0; i -= i & -i) {  
        res += bit\[i\];  
    }  
    return res;  
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章