1. 程式人生 > 實用技巧 >7.14每日一題題解

7.14每日一題題解

計算右側小於當前元素的個數

涉及知識點:

  • 樹狀陣列/離散化/二分

solution:

  • 該題題意就是求每個數的逆序對的個數
  • 求逆序對我們可以用歸併排序或者字首和來做
  • 這裡我們介紹字首和的做法,歸併排序求逆序對可以自行學習
  • 我們倒著將陣列的每一個數輸入,然後求該數的字首和,求完後該位置的數值+1
  • 但是如果我們可以想到假如該值非常大,那麼我們要用很大的數值去存,這樣就會有很多無效的空間
  • 所以我們還需要將所給的數進行離散化

std:

class Solution {
private:
    vector<int> v;
    vector<int> c;
    int lowbit(int x)
    {
        return x&-x;
    }
    int sum(int x)
    {
        int res=0;
        for (int i = x ; i ; i -= lowbit(i)) res += c[i];
        return res;
    }
    void get(vector<int>& nums)
    {
        v.assign(nums.begin(),nums.end());
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
    } 
    void add(int x,int m)
    {
        for(int i = x ; i < c.size() ; i += lowbit(i)) c[i] += m;
    }
public:
    vector<int> countSmaller(vector<int>& nums) {
        vector<int> res;
        int len = nums.size();
        //離散化
        get(nums);
        //樹狀陣列初始化
        c.resize(len + 1);
        for (int i = len-1; i >= 0; i -- )
        {
            int index = lower_bound(v.begin(),v.end(),nums[i]) - v.begin() + 1;
            res.push_back(sum(index-1));
            add(index,1);
        }
        reverse(res.begin(),res.end());
        return res;
    }
};