不得不说对归并的使用很巧妙

也利用两个有序无序数组,其逆序对数一样以及对于有序递增序列,其某个数字的逆序对可以一次求出的性质

class Solution {
  public:
    int InversePairs(vector<int> data) {
        //  边界判断
      if (data.empty() || data.size() == 1) {
        return 0;
      }
      
        //  归并算法的辅助空间和计数器
      std::vector<int> tmp(data.size());
      int count = 0;
      
        //  归并
      div(data, tmp, 0, data.size() - 1, count);
      
      return count;
    }
  private:
    void div(std::vector<int> &data, std::vector<int> &tmp, int left, int right, int &count) {
      // 归并时最少有两个子数组进行组合排序,等于时就需要终止
      if (left >= right) {
        return ;
      }
      
      int mid = left + ((right - left) >> 1);  // 移位操作比除法更快
      div(data, tmp, left, mid, count);
      div(data, tmp, mid + 1, right, count);
      merge(data, tmp, left, mid, right, count);
    }
    
    void merge(std::vector<int> &data, std::vector<int> &tmp, int left, int mid, int right, int &count) {
        //  两个子数组的起始索引和辅助空间的索引
      int fir_arr = left, sec_arr = mid + 1, tmp_index = 0;
      
      while (fir_arr <= mid && sec_arr <= right) {
          //  成立则构成逆序,而该子数组又是有序递增数组,可求总的逆序对
          //  和常规归并排序的差别在于逆序时统计逆序对
        if (data[fir_arr] > data[sec_arr]) {
          tmp[tmp_index++] = data[sec_arr++];
          count += (mid - fir_arr + 1);
          count %= mod;
        } else {
          tmp[tmp_index++] = data[fir_arr++];
        }
      }
      
        //  两个while遍历某一个未遍历完的数组
      while (fir_arr <= mid) {
        tmp[tmp_index++] = data[fir_arr++];
      }
      
      while (sec_arr <= right) {
        tmp[tmp_index++] = data[sec_arr++];
      }
      
        //  拷贝回原数组
      for (tmp_index = 0, fir_arr = left; fir_arr <= right; ++fir_arr, ++tmp_index) {
        data[fir_arr] = tmp[tmp_index];
      }
    }
  private:
    const int mod = 1'000'000'007;
};