Codeforces 873D. Merge Sort 分治 + 构造

传送门:Codeforces 873D

题意:给出一种特殊的归并排序,分治的方法同普通的归并排序一样,只是如果当前待排序的区间已经是有序的,就不会再继续递归了,让你构造一个会调用k次mergesort函数的序列。

思路:因为我们上来就会调用一次mergesort函数,并且只要当前待排序区间不是有序的,那么在该层递归里就会调用两次mergesort,因此可以推出总调用次数一定是个奇数。然后我们递归的构造答案序列(令答案序列初始有序),若k > 2, 我们就将当前区间的a[mid]和a[mid - 1]交换一下,这样可以保证下一层递归传进去的区间一定是个有序区间,这不会样影响k==1时候的退出(按照题给定义,必须当前区间有序才能退出)。交换后k就少了2,一直这样递归构造,出口就是l + 1 == r或者k == 1.

代码:

#include
using namespace std;
const int MAXN = 100010;
int a[MAXN];
int n, k;
void dfs(int l, int r)
{
    if(k == 1 || l + 1 == r) return ;
    k -= 2;
    int mid = (l + r) >> 1;
    swap(a[mid], a[mid - 1]);
    dfs(l, mid);
    dfs(mid, r);
}
int main()
{
    cin >> n >> k;
    if(k % 2 == 0) {
        cout << -1;
        return 0;
    }
    for(int i = 0; i < n; i++) a[i] = i + 1;
    dfs(0, n);
    if(k != 1) cout << -1;
    else
    for(int i = 0; i < n; i++)
        printf("%d ", a[i]);
}


你可能感兴趣的:(codeforces,分治,构造)