数组中的逆序对

文章介绍了如何使用归并排序算法来统计数组中的逆序对数量。在归并过程中,通过比较并计算来自不同有序段的元素构成的逆序对,逐步累加到结果中。此外,还提到了一种处理原数组的方法,通过对数组元素减去一个常数t并求前缀和,然后同样应用归并排序来找到顺序对。
摘要由CSDN通过智能技术生成

问题描述

解决思路

采用归并排序,在合并两个有序段时,统计由分别来自两个有序段的数字构成的逆序对,便可得到当前整段的逆序对数量。

核心代码

class Solution {
public:
    int res=0;
    const int mod=1000000007;
    int InversePairs(vector<int> data) {
        vector<int> temp(data.size());
        merge_sort(data,temp,0,data.size()-1);
        return res;
    }
    void merge_sort(vector<int>& arr,vector<int>& temp,int l,int r){
        if(l>=r){
            return;
        }
        int mid=(l+r)/2;
        merge_sort(arr, temp,l, mid);
        merge_sort(arr, temp,mid+1, r);
        merge(arr,temp,l,r);
    }
    void merge(vector<int>& arr,vector<int>& temp,int l,int r){
        int mid=(l+r)/2;
        int i=l,j=mid+1,k=0;
        // vector<int> temp(r-l+1);
        while(i<=mid&&j<=r){
            if(arr[i]>arr[j]){
                temp[k++]=arr[j++];
                res=(res+mid-i+1)%mod;
            }
            else{
                temp[k++]=arr[i++];
            }
        }
        while(i<=mid) temp[k++]=arr[i++];
        while(j<=r) temp[k++]=arr[j++];
        for(int t=0;t<r-l+1;++t) arr[t+l]=temp[t];
    }
};

活学活用

解法

原数组每一项都减去t,求前缀和数组中的顺序对(单独一项大于0也计入)

代码

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll res=0;
void merge(vector<ll>& arr,vector<ll>& temp,ll l,ll r){
    ll mid=l+r>>1;
    ll i=l,j=mid+1,k=0;
    // vector<ll> temp(r-l+1);
    while(i<=mid&&j<=r){
        if(arr[i]>arr[j]){
            temp[k++]=arr[j++];
            // res=(res+mid-i+1)%mod;
        }
        else{
            res=(res+r-j+1)%mod;
            temp[k++]=arr[i++];
        }
    }
    while(i<=mid) temp[k++]=arr[i++];
    while(j<=r) temp[k++]=arr[j++];
    for(ll t=0;t<r-l+1;++t) arr[t+l]=temp[t];
}
void merge_sort(vector<ll>& arr,vector<ll>& temp,ll l,ll r){
    if(l>=r){
        return;
    }
    ll mid=l+r>>1;
    merge_sort(arr, temp,l, mid);
    merge_sort(arr, temp,mid+1, r);
    merge(arr,temp,l,r);
}
int main( )
{
    // freopen("input.txt","r",stdin);
    ll n,t,x;
    cin>>n>>t;
    vector<ll> sum(n+1,0);//第一项取0,所有非负项都会以与第一项构成顺序对
    vector<ll> temp(n+1);
    for(ll i=1;i<=n;++i){
        cin>>x;
        sum[i]=sum[i-1]+x-t;;
    }
    merge_sort(sum,temp,0,n);
    // cout<<(-res+n*(n+1)/2)%mod<<endl;
    cout<<res<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值