LeetCode 493. Reverse Pairs

题目链接:https://leetcode.com/problems/reverse-pairs/

题意:求数组$nums$中所有满足$i<j$且$nums[i]>2*nums[j]$的数组对(i,j)的数目。

思路:该题很明显是逆序对的变形题,逆序对的条件是$nums[i]>nums[j]$,这里仍然使用树状数组,因此可以将原数组扩大一倍,对每个元素的二倍也存储,并记录其下标,按照数的大小排序,所有是原数组二倍的数下标都加上$nums.size()$(为了树状数组的需要,下标从1开始),在遍历时,遇到原数组的数时进行查询,查找扩大二倍后仍小于该数的个数,遇到下标大于$nums.size()$的数时对树状数组进行更新,树状数组对应位置加1。

class Solution {
public:
    //s为树状数组,修改下标为x的数,树状数组大小为n
    void update(int *s,int x,int n) {
        while (x <= n) {
            s[x] += 1;
            x += (x&-x);
        }
    }
    //查询
    int query(int *s, int x) {
        int sum = 0;
        while (x > 0) {
            sum += s[x];
            x -= (x&-x);
        }
        return sum;
    }
    int reversePairs(vector<int>& nums) {
        //第一维为数的大小(包括原来的数扩大二倍),第二维为下标(扩大2倍的数下标增大nums.size())
        vector<pair<long long, int> >v;
        for (int i = 0;i < nums.size();i++) {
            v.push_back(make_pair(nums[i], i+1));
            v.push_back(make_pair(nums[i] * 2LL, i+1 + nums.size())); //下标从1开始
        }
        int *s = new int[nums.size() + 1];
        memset(s, 0, (nums.size() + 1)*4);
        int ans = 0;
        sort(v.begin(), v.end());
        for (int i = 0;i < v.size();i++) {
            if (v[i].second <= nums.size()) //原数组中的数则查询
                ans += (query(s,nums.size())-query(s, v[i].second));
            else update(s,v[i].second-nums.size(),nums.size()); //对于2*nums[k]则需要更新
        }
        return ans;
    }
};

  

原文地址:https://www.cnblogs.com/dlutjwh/p/11294537.html