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;
    }
};
posted @ 2022-02-20 11:34  South1999  阅读(111)  评论(0编辑  收藏  举报