PAT_A1089
PAT甲级1089.
目录
A1089
题目
样例
样例1
输入:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
输出:
Insertion Sort
1 2 3 5 7 8 9 4 6 0
样例2
输入:
10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6
输出:
Merge Sort
1 2 3 8 4 5 7 9 0 6
思路和坑点
根据插入排序和归并排序的特点,插入排序前一部分有序,后一部分和原序列相同。一旦排除插入排序,则是归并排序,对原始序列模拟归并排序,当和中间序列相同时再进行一次归并几位所求结果。
AC代码
#include<bits/stdc++.h>
using namespace std;
int main(void){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt","r",stdin);
#endif
int n,i,j;
cin>>n;
vector<int> v(n),vs(n); //两个序列,v为原始序列,vs为中间序列
for(i=0;i<n;i++) cin>>v[i];
for(i=0;i<n;i++) cin>>vs[i];
for(i=0;i<n-1;i++){ //找vs中前边不是有序的位置
if(vs[i]>vs[i+1]){
j=i+1; break;
}
}
for(j;j<n;j++){ //后半部分如果还和原始序列相同,则是插入 ,否则是归并
if(v[j]!=vs[j]) break;
}
if(j==n){ //如果后半部分和原始序列相同,j会走到n
puts("Insertion Sort");
sort(v.begin(),v.begin()+i+2); //将前半部分排序,统一都在v上操作,这样最后序列输出可以统一
}
else{
puts("Merge Sort");
int step=2,flag=1; //step表示归并段的长度,初始化为2,flag表示是否到达中间序列
while(flag){
if(v==vs) flag=0; //如果归并到给定的中间结果,修改flag=0,然后再归并一次之后结束循环
for(i=0;i<n/step;i++) //整齐部分的归并段排序,每个段内使用快排
sort(v.begin()+i*step,v.begin()+(i+1)*step);
sort(v.begin()+i*step,v.end()); //结尾部分不够整个step的单独处理
step*=2; //归并步长加倍
}
}
for(int i=0;i<n;i++){ //输出结果
if(i) putchar(' ');
printf("%d",v[i]);
}
return 0;
}