排序
归并排序
分治
- 选取分界点进行递归,这里选取中间点(l+r)>>1
- 以中间值进行左右分别递归,排序
- 将左右值合并
平均复杂度: nlogn
实现思路
每次都选取一个中间值,然后分开递归排序,i = l,j = mid + 1;如果小的就保存到tmp数组直到 i / j 跑到结尾
然后将剩下的进行移动 - 中间点
- 左右递归
- 合并
算法模板
#include <iostream>
using namespace std;
const int maxn=1e6+5;
int q[maxn], tmp[maxn];
void merge_sort(int q[],int l,int r){
if(l>=r) return ;
int mid=l+r>>1 ;//选点
merge_sort(q,l,mid);//左右递归
merge_sort(q,mid+1,r);
int i=l, j=mid+1, k=0;//合并
while(i<=mid && j<=r){
if(q[i]<=q[j]) tmp[k++] = q[i++];
else tmp[k++] = q[j++];
}
while(i<=mid) tmp[k++] = q[i++];
while(j<=r) tmp[k++] = q[j++];
for(int i=l, j=0; i<=r; i++,j++) q[i]=tmp[j];//改变原数组值
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&q[i]);
merge_sort(q,1,n);
for(int i=1;i<=n;++i) printf("%d ",q[i]);
return 0;
}
逆序对的数量
#include <iostream>
using namespace std;
const int maxn=1e5+5;
int q[maxn], tmp[maxn];
typedef long long ll;
ll ans = 0;
void merge_sort(int q[],int l,int r){
if(l>=r) return;
int mid = l+r >> 1;
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
int i=l,j=mid+1,k=0;
while(i <= mid && j <= r){
if(q[i]>q[j]) {
tmp[k++]=q[j++];
ans+=mid-i+1;
}
else tmp[k++]=q[i++];
}
while(i<=mid) tmp[k++]=q[i++];
while(j<=r) tmp[k++]=q[j++];
for(int i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];
}
int main(){
int n;cin>>n;
for(int i=0;i<n;++i) cin>>q[i];
merge_sort(q,0,n-1);
cout<<ans<<endl;
return 0;
}
翻天覆地
描述
给定一个长度为n
的数组a[]
,如果i < j
且a[i] > 2*a[j]
我们就将(i, j)
称作一个翻转对。问数组中有多少翻转对。
输入
第一行输入包含两个整数n。
第二行输入数组a的元素,空格分隔。分别表示a[0],a[1],a[2]…a[n-1]。
输出
输出一个数组中翻转对的数量。
输入样例 1
5
1 3 2 3 1
输出样例 1
2
提示
0 < n <= 10^5
-2*10^9 <= a[i] <= 2*10^9
AC代码
#include <iostream>
using namespace std;
const int maxn=1e5+5;
#define IOS std::ios::sync_with_stdio(false);std::cin.tie(0);
int q[maxn],tep[maxn];
typedef long long ll;
ll ans=0;
void merge_sort(int q[],int l,int r){
if(l>=r) return ;
int mid=l+r>>1;
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
int x=l,y=mid+1,m=0;//如果一边排序一边统计会出现少算的情况,所以在每一次排序前先进行统计比较
while(x<=mid){
while((y<=r)&&((ll)q[x]>2*(ll)q[y])) y++;//注意数据范围
x++;
ans+=y-mid-1;
}
int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r){
if(q[i]<=q[j]) tep[k++]=q[i++];
else tep[k++]=q[j++];
}
while(i<=mid) tep[k++]=q[i++];
while(j<=r) tep[k++]=q[j++];
for(int i=l,j=0;i<=r;i++,j++) q[i]=tep[j];
}
int main(){
IOS;
int n;cin>>n;
for(int i=0;i<n;++i){
cin>>q[i];
}
merge_sort(q,0,n-1);
cout<<ans<<endl;
return 0;
}