LeetCode493翻转对(树状数组+离散化)

题目链接Leetcode493
在这里插入图片描述

思路:同求逆序数一样的更新查询,关键在于离散化部分,我们要得到原序列与2倍序列所对应的位置,并且为了最后能够常数时间查到原序列对应位置的2倍序列的数值的位置,用个哈希函数 i d % n id\%n id%n表示同位置的对应的位置,设一个rnk1表示原序列位置,rnk2表示2倍序列的位置,题就解决了。关于离散化那个用二分处理的可能不好操作,用结构体排序会快点

Code

class Discretization {
public:
    int id; //组号
    //小于n表示第i组原序列 大于n表示第i%n组原序列得2倍
    long long val;
    bool operator < (const Discretization& A) {
        return val < A.val;
    }
};

class Solution {
public:
    int reversePairs(vector<int>& nums) {
        n = nums.size();
        memset(c, 0, sizeof(c));
        //关键:离散化
        //找到原序列和2倍原序列对应得位置
        for (int i=0; i<n; i++) {
            discrete[i].id=i;
            discrete[i].val=nums[i];
            discrete[i+n].id=i+n;
            discrete[i+n].val=nums[i]*2LL;
        }
        sort(discrete, discrete+2*n);
        int tag=0; //去重标记
        for (int i=0; i<2*n; i++) { //预处理两个序列的离散化序列
            if (i==0 || discrete[i].val!=discrete[i-1].val) tag++;
            
            if (discrete[i].id<n) rnk1[discrete[i].id]=tag;
            else rnk2[discrete[i].id-n]=tag;
        }
        
        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans += i-query(rnk2[i]); //查询两倍i的数所得到的贡献
            update(rnk1[i], 1); //i位置对后面的贡献            
        }
        return ans;
    }
private:
    int c[100005], n;
    Discretization discrete[100005];
    int rnk1[50005],rnk2[50005];
    inline int lowbit(int x) {
        return x & (-x);
    }
    void update(int idx, int num) {
        while(idx <= 100000) {
            c[idx] += num;
            idx += lowbit(idx);
        }
    }
    int query(int idx) {
        int sum = 0;
        while (idx > 0) {
            sum += c[idx];
            idx -= lowbit(idx);
        }
        return sum;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小胡同的诗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值