• CodeForces 873D Merge Sort 构造 分治


    题意

    给出一个归并排序的算法(mergesort),如果对于当前区间([l, r))是有序的,则函数直接返回。
    否则会分别调用(mergesort(l, mid))(mergesort(mid, r)),其中(mid = left lfloor frac{l+r}{2} ight floor)
    最后合并左右两个子区间

    下面请你构造一个(1 sim n)的排列,并且恰好调用(k)(mergesort)函数完成排序

    分析

    首先,对函数的调用次数一定是奇数次
    因为除去最开始对函数的调用,之后每次调用函数都是对左右区间成对调用的
    设一开始排列(p)是从(1)(n)的顺序排列
    模拟(mergesort)函数的调用进行构造,假设当前区间为([l,r),(r-l>1)),并且当前调用次数未满(k)
    那么交换(p[mid-1])(p[mid]),则区间([l,r))变为无序,函数调用次数增加(2)
    左右两个子区间仍然是有序的,不断递归进行处理直到调用次数等于(k)或对所有区间处理完毕

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define REP(i, a, b) for(int i = a; i < b; i++)
    
    const int maxn = 100000 + 10;
    
    int n, k;
    int a[maxn];
    
    void solve(int l, int r) {
    	if(!k || r - l == 1) return;
    	k--;
    	int mid = (l + r) / 2;
    	swap(a[mid], a[mid - 1]);
    	solve(l, mid);
    	solve(mid, r);
    }
    
    int main() {
    	scanf("%d%d", &n, &k);
    	k--;
    	if(k & 1) { printf("-1
    "); return 0; }
    	k >>= 1;
    	REP(i, 0, n) a[i] = i + 1;
    	solve(0, n);
    	if(k) printf("-1
    ");
    	else REP(i, 0, n) printf("%d ", a[i]);
    	printf("
    ");
    
    	return 0;
    }
    
  • 相关阅读:
    Windows环境下 配置memcached (php)
    谈谈我是怎么学习PHP的(一)
    重编译Linux命令源代码
    php面向对象学习
    Windows文件系统漏洞
    十分钟能学会的框架,MVC+20个常用函数
    linux系统安装软件方法大全
    oracle基本操作
    MySQL的limit查询优化
    C# winform 可视化操作 Excel文件并读取数据
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/7668954.html
Copyright © 2020-2023  润新知