题目链接: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; } };