LeetCode 5999. 统计数组中好三元组数目
2022.2.19双周周赛的第四题统计数组中好三元组数目,翻车了,题目要求可点击链接直接查看,当时的思路只想到把nums2映射成[0,1,2,...,n-1]的数组,然后nums1根据相同映射规则也进行改变,然后求nums1中满足x<y<z且\(pos_x<pos_y<pos_z\)的三元组数,可以每次固定y,然后求位置小于y且值也小于y的数的个数,记为less,然后用n - y - (\(pos_y\) - less)求出位置比y大且值也比y大的数的个数(n-y求的是数组内比y大的数的个数,\(pos_y\) - less求的是位置小于y但值大于y的数的个数,相减就求出位置比y大且值也比y大的数的个数),然后用less与这部分值相乘就求出y作为中间数字的三元组个数,最后遍历所有数字以求出最后答案。当时没想到用树状数组求,想到的方法都是O(n^2)的复杂度,肯定会超时,树状数组时间复杂度是O(nlogn),我参考了这篇博客学习树状数组详解,这篇博客看过不下5遍了,每次只是背模板一样把关键代码背下来,没理解,很难想到去用,这次仔细看了一遍,基本上已经理解了。
class Solution {
public:
vector<int> tree;
int lowbit(int x)
{
return x&(-x);
}
void update(int i, int n)
{
while(i <= n)
{
tree[i] += 1;
i += lowbit(i);
}
}
long long getsum(int i)
{
long long res = 0;
while(i > 0)
{
res += tree[i];
i -= lowbit(i);
}
return res;
}
long long goodTriplets(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
tree.resize(n+1);
vector<int> pos(n);
for(int i = 0; i < n; ++i)
{
pos[nums2[i]] = i;
}
for(int i = 0; i < n; ++i)
{
nums1[i] = pos[nums1[i]] + 1;
}
update(nums1[0], n);
long long ans = 0;
for(int i = 1; i < n - 1; ++i)
{
long long less = getsum(nums1[i]);
ans += less * (n - nums1[i] - (i - less));
update(nums1[i], n);
}
return ans;
}
};