原题传送门:数列排序 - 洛谷
题目给出了限定条件,数列中任意两个数都不会相同。
把每个数都看作一个人,升序之后的序列他们的位次从1开始排到n,也就是说他们都有一个最终的位置。
比如现在第一个人现在是位次9的,那就需要将位次1的回来,然后让这个人滚出克,一次操作完成一次排座位(最好的情况是两个人交换位置,两个人都完成了排座位,所以要将前面的那个人放到后面去)
AC代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+1;
int n,a[MAXN],ans,b[MAXN],as[MAXN];
unordered_map<int,int>m;
void merge_sort(int l,int r){
if(l==r)return;
int mid=(l+r)>>1;
merge_sort(l,mid);
merge_sort(mid+1,r);
int i=l,j=mid+1,k=l;
while(i<=mid&&j<=r){
if(a[i]<a[j])b[k++]=a[i++];
else b[k++]=a[j++];
}
while(i<=mid)b[k++]=a[i++];
while(j<=r)b[k++]=a[j++];
for(i=l;i<=r;i++)a[i]=b[i];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
as[i]=a[i];
m[a[i]]=i;//as[1]在第一个,但是有可能不是第一个
}
merge_sort(1,n);
//a为有序,as为原序列
for(int i=1;i<=n;i++){
if(a[i]!=as[i]){//如果as[i]不是这个位置的,让a[i]归位.
ans++;
int x=m[a[i]];//a[i]的位置x变成as[i]的位置
m[as[i]]=x;
as[x]=as[i];//前面的跑到后面去,待定.
}
}
printf("%d",ans);
return 0;
}
STL里面好像是有一个stable_sort的,内部归并排序...
这道题类似的还有逆序对(逃