• 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;
        }
    };
    

      

  • 相关阅读:
    [bzoj2038] [2009国家集训队]小Z的袜子
    浅谈莫队
    [bzoj2754] [SCOI2012]喵星球上的点名
    [bzoj3676] [APIO2014]回文串
    [bzoj5472] 数列
    [bzoj5457] 城市
    [bzoj1023] [SHOI2008]cactus仙人掌图
    [bzoj2125] 最短路
    [bzoj5473] 仙人掌
    读《深入理解Elasticsearch》点滴-查询评分
  • 原文地址:https://www.cnblogs.com/dlutjwh/p/11294537.html
Copyright © 2020-2023  润新知