problem
1035 插入与归并 (25分)
根据维基百科的定义:
插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。
归并排序进行如下迭代操作:首先将原始序列看成 N 个只包含 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 个有序的序列。
现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?
输入格式:
输入在第一行给出正整数 N (≤100);随后一行给出原始序列的 N 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。
输出格式:
首先在第 1 行中输出Insertion Sort表示插入排序、或Merge Sort表示归并排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。
输入样例 1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
输出样例 1:
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
输出样例 2:
Merge Sort
1 2 3 8 4 5 7 9 0 6
solution
//1.两个排序不会,磨了一个小时
//2.学习一下神奇的插入排序写法。
//3.几路归并没说,所以枚举。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 110;
int n, a[maxn], b[maxn],c[maxn], ok;
void Merge(int a[]){
//传说中的归并排序写法,学习了。。。
//从底部往上,每次局部快排。。。
for(int i = 1; i <= n; i*=2){
for(int j = 0; j < n; j+=i){
if(j+i<=n)sort(a+1+j,a+1+j+i);
else sort(a+1+j,a+n+1);
}
//output
int ok = 1;
for(int j = 1; j <= n; j++)
if(a[j]!=b[j]){ok=0;break;}
if(ok){
cout<<"Merge Sort\n";
i *= 2;//手动下一轮排序qwq(亏我之前还全局开关等下一轮)
for(int j = 0; j < n; j+=i){
if(j+i<=n)sort(a+j+1,a+j+i+1);
else sort(a+j+1,a+n+1);
}
for(int j = 1; j < n; j++)cout<<a[j]<<" ";cout<<a[n];cout<<"\n";
}
}
/*
if(l==r)return ;
int mid = (l+r)/2;
Merge(l,mid);
//for(int i = 1; i <= n; i++)cout<<a[i]<<" ";cout<<"\n";
if(ok){cout<<"Merge Sort\n";for(int i = 1; i <= n; i++)cout<<a[i]<<' '; cout<<"\n";ok=0;}
ok = 1;
for(int i = 1; i <= n; i++)
if(a[i]!=b[i]){ok=0;break;}
Merge(mid+1,r);
//for(int i = 1; i <= n; i++)cout<<a[i]<<" ";cout<<"\n";
if(ok){cout<<"Merge Sort\n";for(int i = 1; i <= n; i++)cout<<a[i]<<' '; cout<<"\n";ok=0;}
ok = 1;
for(int i = 1; i <= n; i++)
if(a[i]!=b[i]){ok=0;break;}
int i = l, j = mid+1, k=1;
int t[110];
while(i<j && i<=mid && j<=r){
if(a[i]<a[j])t[k] = a[i++];
else t[k] = a[j++];
k++;
}
while(i<=mid)t[k++]=a[i++];
while(j<=r)t[k++]=a[j++];
k = 1;
//for(int i = 1; i <= n; i++)cout<<a[i]<<" ";cout<<"\n";
for(int ii=l; ii <= r; ii++)
a[ii]=t[k++];
if(ok){cout<<"Merge Sort\n";for(int i = 1; i <= n; i++)cout<<a[i]<<' '; cout<<"\n";ok=0;}
ok = 1;
for(int i = 1; i <= n; i++)
if(a[i]!=b[i]){ok=0;break;}
//for(int i = 1; i <= n; i++)cout<<a[i]<<" ";cout<<"\n";
*/
}
void swap(int &x, int &y){
int t = x; x = y, y = t;
}
bool Insert(){
for(int i = 2; i <= n; i++){
//害怕!!!插入排序!!!∑(゚Д゚ノ)ノ
sort(a+1,a+i+1);
/*
int tt = a[i], j = i-1;
for(; j>= 1; j--)
if(a[j]>a[j+1])swap(a[j+1],a[j]);
*/
//output
int ok = 1;
for(int j = 1; j <= n; j++)
if(a[j]!=b[j]){ok=0;break;}
if(ok){
cout<<"Insertion Sort\n";
sort(a+1,a+i+2);//......
for(int j = 1; j < n; j++)cout<<a[j]<<" "; cout<<a[n]<<"\n";
return true;
}
}
return false;
}
int main(){
cin>>n;
for(int i = 1; i <= n; i++){cin>>a[i];c[i]=a[i];}
for(int i = 1; i <= n; i++)cin>>b[i];
if(!Insert()){//测试点3,可能有两种都有的情况
//a数组被Insert改掉了,,归并当然算不出来啊卧槽。。。
Merge(c);
}
//for(int i = 1; i <= n; i++)cout<<a[i]<<' ';
return 0;
}