标签:pre void 扩大 变形 turn second sum tor back
题目链接: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;
}
};
标签:pre void 扩大 变形 turn second sum tor back
原文地址:https://www.cnblogs.com/dlutjwh/p/11294537.html