1. 程式人生 > >Educational Codeforces Round 30 D. Merge Sort

Educational Codeforces Round 30 D. Merge Sort

全部 不用 () ace str ron cout == -s

題意:給你n和k,n代表有多少個數,k代表幾次操作,求一個1到n的序列,要k次mergesort操作才能還原

Examples Input
3 3
Output
2 1 3 
Input
4 1
Output
1 2 3 4 
Input
5 6
Output
-1

思路:看了很久才看懂題目的意思,根據題意對於一個[l,r)的區間,如果是亂的,你會先mergesort一下,如果已經是遞增的,
    那麽就不用繼續往下操作了;如果不是遞增的,那麽就要分一下,對左邊[l,mid)操作,右邊[mid,r)操作,等到左邊和
    右邊的都排完,然後最後再排一下,這樣的操作次數是2。所以對於每一個樣例,k肯定是個奇數,因為你最開始要操作一
    次全區間,然後才開始遞歸,而且k不會大於等於2*n,因為全部分開,操作最多也就是2*n-1(自己畫一下圖就知道了)。
    我們就從末狀態開始,往前走,每次dfs把a[mid]和a[mid-1]換一下,因為a[mid-1]是在左邊區間的,a[mid]是在右
    邊區間的,所以你需要左邊排一下,右邊排一下,這樣操作次數是2,最後排一下,就是這個最後排一下,可以把我們交換
    的還原(我猜應該是這樣233333)。細節就看代碼吧。

代碼:
#include<iostream>
#include<string.h>
using namespace std;

const int maxn=1e5+5;

int a[maxn],n,k;

void dfs(int l,int r){
if(k==1||r<=l+1)return ;
k-=2;
int mid=(l+r)/2;
int x=a[mid];
a[mid]=a[mid-1]; a[mid-1]=x;
//因為左邊的區間是[l,mid),右邊的區間是[mid,r),所以應該要把a[mid-1]和a[mid]換一下
//這樣就需要兩次mergesort才能還原,(一次左邊,一次右邊,最後總的一次還原)
dfs(l,mid);
dfs(mid,r);
}
int main(){
cin>>n>>k;
if(k>=2*n||k%2==0){
cout<<-1<<endl;
return 0;
}
for(int i=1;i<=n;i++)a[i]=i;
dfs(1,n+1);
for(int i=1;i<=n;i++){
if(i!=1)cout<<‘ ‘;
cout<<a[i];
}
cout<<endl;
return 0;
}

Educational Codeforces Round 30 D. Merge Sort