Tony's Log

Algorithms, Distributed System, Machine Learning

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

My naive Fenwick solution (value space) failed with the last test case in which there's INT_MIN\INT_MAX..

So I learnt a smarter thought on Fenwick:
https://leetcode.com/discuss/79907/summary-divide-conquer-based-binary-indexed-based-solutions

It is in Index Space - which saves quite a bit of space. The basic idea

1. In the Fenwitk tree, we only store indices - but these indices mean i-th large in the input value space. That means we need a sort on all target values.

2. In Fenwick tree, index 0 is the root and we don't use it !

I simply translated the Java code in the above link to C++:

class Solution {
    //    Fenwick tree ops
    void update(vector<int>& bit, int index, int value) 
    {
        while (index < bit.size()) 
        {
            bit[index] += value;
            index += index & -index;
        }
    }

    int query(vector<int>& bit, int index) 
    {
        int sum = 0;
        while (index > 0) 
        {
            sum += bit[index];
            index -= index & -index;
        }
        return sum;
    }
    //
    int getIndex(vector<long long>& nums, long long val)
    {
        int r = lower_bound(nums.begin(), nums.end(), val) - nums.begin();
        return r;
    }
public:
    int countRangeSum(vector<int>& nums, int lower, int upper) 
    {
        int n = nums.size();
        if(!n) return 0;

        vector<long long> sum(nums.size() + 1);
        vector<long long> cand(3*sum.size() + 1);
        
        //    Get pre-sum and cand number array ready
        cand.push_back(sum[0]);
        cand.push_back(lower + sum[0] - 1);
        cand.push_back(upper + sum[0]);        
        for (int i = 1; i < sum.size(); i++) {
            sum[i] = sum[i - 1] + nums[i - 1];
            cand.push_back(sum[i]);
            cand.push_back(lower + sum[i] - 1);
            cand.push_back(upper + sum[i]);
        }        

        //    in Fenwick tree index 0 is the root, we don't use it
        cand.push_back(LLONG_MIN);
        sort(cand.begin(), cand.end());

        //    Fenwick 
        vector<int> fen(cand.size()); // Value-Sorted index based instead of value based
        for(int i = 0; i < sum.size(); i ++)
        {
            update(fen, getIndex(cand, sum[i]), 1);
        }
        
        int count = 0;
        for(int i = 1; i < sum.size(); i ++)
        {
            // remove last checked elem
            update(fen, getIndex(cand, sum[i - 1]), -1); 

            count += query(fen, getIndex(cand, upper + sum[i - 1]));
            count -= query(fen, getIndex(cand, lower + sum[i - 1] - 1));
        }
        return count;
    }
};

And an alternative solution is to use MergeSort to count, also interesting:

https://leetcode.com/discuss/79154/short-%26-simple-o-n-log-n

 

posted on 2016-01-27 05:57  Tonix  阅读(205)  评论(0)    收藏  举报