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;
    }
};
原文地址:https://www.cnblogs.com/QFNU-ACM/p/13298659.html