码迷,mamicode.com
首页 > 编程语言 > 详细

校内集训 miku set模拟冒泡排序 逆序对

时间:2018-11-04 15:34:04      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:return   \n   amp   个数   ace   复杂   逆序   log   pre   

题意

  • 给你一个长为\(n\)的序列,进行\(m\)次操作,每次对一个区间进行排序,求最后的序列\((n <= 1500, m <= 1e6)\)

这道题目思维难度挺大的

对于一个序列,排序的本质就是消除里面的所有逆序对

考虑冒泡排序的过程,每次也是交换\(a[i]>a[i+1]\)这个逆序对

这样子交换最多有\(n^2\)

那么我们可以用一个数据结构模拟冒泡排序交换逆序对这个过程

用一个\(set\)维护所有逆序对的位置

每次暴力删除区间内所有逆序对

再把新产生的逆序对加入\(set\)

复杂度\(O((n^2+m)\log n)\)

Codes

#include <set>
#include <cstdio>

using namespace std;

const int N = 1500 + 10;

set<int> S;
set<int>::iterator it;

int a[N], n, q, L, R;

int main() {
    //freopen("miku.in", "r", stdin);
    //freopen("miku.out", "w", stdout);

    scanf("%d%d%d%d", &n, &q, &L, &R);
    for (int i = 1; i <= n; ++ i) 
        scanf("%d", &a[i]);
    for (int i = 1; i < n; ++ i) 
        if (a[i] > a[i + 1]) 
            S.insert(i);
    S.insert(n), a[n + 1] = 2e9;

    while (q --) {
        int l, r; scanf("%d%d", &l, &r);
        for (; *(it = S.lower_bound(l)) < r; S.erase(it ++)) {
            swap(a[*it], a[*it + 1]);
            if(a[*it - 1] > a[*it]) S.insert(*it - 1);
            if(a[*it + 1] > a[*it + 2]) S.insert(*it + 1);
        }
    }

    for (int i = L; i <= R; ++ i)
        printf("%d%c", a[i], i == R ? ‘\n‘ : ‘ ‘);

    return 0;
}

校内集训 miku set模拟冒泡排序 逆序对

标签:return   \n   amp   个数   ace   复杂   逆序   log   pre   

原文地址:https://www.cnblogs.com/brunch/p/9903888.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!