zoukankan      html  css  js  c++  java
  • noi.ac #32 快速排序归并排序应用

    (des)
    给定长度为 (n) 的数组,要求翻转一段区间 ([l, r]) 使其升序排列。
    要求 (sum r - l + 1 <= 2e7)

    (sol)
    考虑快速排序,每次选择一个 (mid),把 (<= mid) 的数放大左边, (>= mid)

    的数放到右边,递归下去。
    (<= mid) 的数看做 (0), (>= mid) 的数看做 (1), 就相当于 (0/1) 序列排

    序,类似归并排序,每次把左右两部分排好序,然后将其合并,对于 (0/1) 序列

    而言,排好序等价于前面都是 (0), 后面都是 (1),这样的话,每次将左半边的

    (1) 和右半边的 (0) 进行翻转。

    (code)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cctype>
    #include <cstdlib>
    
    #define N 50005
    using namespace std;
    
    int n, a[N], id[N];
    
    void output(int l, int r) {
    	printf("%d %d
    ", l, r);
    	for(; l < r; l ++, r --) swap(a[l], a[r]);
    }
    
    int Msort(int l, int r, int val) {
    	if(l > r) return 0;
    	if(l == r) return a[l] < val;
    	int mid = (l + r) >> 1;
    	int a = Msort(l , mid , val) , b = Msort(mid + 1 , r , val);
    	if(l + a <= mid && mid + b <= r && b) output(l + a, mid + b);
    	return a + b;
    }
    
    void Qsort(int l, int r, int L, int R) {
    	if(l >= r || L > R) return;
    	int mid = (L + R) >> 1, tmp;
    	tmp = Msort(l, r, mid);
    	Qsort(l, l + tmp - 1, L, mid - 1), Qsort(l + tmp, r, mid + 1, R);
    }
    
    int main() {
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    	Qsort(1, n, 0, 1000000000);
    	puts("-1 -1");
    	return 0;
    }
    
  • 相关阅读:
    树状数组
    线段树
    最短路(FLOYD)
    欧拉函数
    筛素数
    并查集
    背包方案数问题(礼物)
    [BeijingWc2008]雷涛的小猫
    受欢迎的牛[HAOI2006]
    删除物品[JLOI2013]
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9708166.html
Copyright © 2011-2022 走看看