https://www.luogu.com.cn/problem/P1177
分治思想的完美体现。
每次把待排序的区间一分为二,将两个子区间排序,然后将两个已经排好序的序列合并。
#include<bits/stdc++.h>
#define endl '\n'
#define pii pair<int,int>
using namespace std;
using ll = long long;
const int maxn = 1e5+3;
int a[maxn],b[maxn];
void merge(int l,int mid,int r)
{
int p=l,q=mid+1;
for(int i=l;i<=r;i++)
{
if(q>r||(p<=mid&&a[p]<=a[q])) b[i]=a[p++];
else b[i]=a[q++];
}
for(int i=l;i<=r;i++)
a[i]=b[i];
}
void merge_sort(int l,int r)
{
if(l==r) return ;
int mid=(l+r)/2;
merge_sort(l,mid);
merge_sort(mid+1,r);
merge(l,mid,r);
}
void solve()
{
int n; cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
merge_sort(1,n);
for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; T=1;
while(T--)
solve();
return 0;
}
求逆序对
https://ac.nowcoder.com/acm/contest/21763/C
要求
i
<
j
i<j
i<j &&
a
[
i
]
>
a
[
j
]
a[i]>a[j]
a[i]>a[j] 即求归并排序的合并过程中,左半区间不为空时,选择右半区间时,左半区间元素的个数和。
#include<bits/stdc++.h>
#define endl '\n'
#define pii pair<int,int>
using namespace std;
using ll = long long;
const int maxn = 1e5+3;
int a[maxn],b[maxn];
int ans=0;
void merge(int l,int mid,int r)
{
int p=l,q=mid+1;
for(int i=l;i<=r;i++)
{
if(q>r||(p<=mid&&a[p]<=a[q])) b[i]=a[p++];
else b[i]=a[q++],ans+=mid-p+1;
}
for(int i=l;i<=r;i++)
a[i]=b[i];
}
void merge_sort(int l,int r)
{
if(l==r) return ;
int mid=(l+r)/2;
merge_sort(l,mid);
merge_sort(mid+1,r);
merge(l,mid,r);
}
void solve()
{
int n; cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
merge_sort(1,n);
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; T=1;
while(T--)
solve();
return 0;
}