问题描述
解决思路
采用归并排序,在合并两个有序段时,统计由分别来自两个有序段的数字构成的逆序对,便可得到当前整段的逆序对数量。
核心代码
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;
}