洛谷P2824 [HEOI2016/TJOI2016]排序 题解

洛谷P2824 [HEOI2016/TJOI2016]排序 题解

题目在此

题目描述

在 2016 年,佳媛姐姐喜欢上了数字序列。因而她经常研究关于序列的一些奇奇怪怪的问题,现在她在研究一个难题,需要你来帮助她。
这个难题是这样子的:给出一个 1 到 n n n 的排列,现在对这个排列序列进行 m m m 次局部排序,排序分为两种:

0 l l l r r r 表示将区间 [ l l l, r r r] 的数字升序排序
1 l l l r r r 表示将区间 [ l l l, r r r] 的数字降序排序

注意,这里是对下标在区间 [ l , r l,r l,r] 内的数排序。

最后询问第 q q q 位置上的数字。

输入格式

输入数据的第一行为两个整数 n n n m m m n n n 表示序列的长度, m m m 表示局部排序的次数。
第二行为 n n n 个整数,表示 1 到 n n n 的一个排列。
接下来输入 m m m 行,每一行有三个整数 o p op op, l l l, r r r
o p op op为 0 代表升序排序,
o p op op 为 1 代表降序排序,
l l l, r r r 表示排序的区间。
最后输入一个整数 q q q,表示排序完之后询问的位置

输出格式

输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第 q q q 位置上的数字。

输入输出样例

输入

6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3

输出

5

思路

这里提供一个暴力的做法,我们可以直接用桶排加max,min的优化,这个题就能水过

(记住开 O 2 O2 O2喔!)

代码

#include <cstdio>
#include <vector>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <map>
#include <ctime>
#include <set>
#define ph puts("")
#define pk putchar(' ')
using namespace std;
typedef long long ll;
template <class T>
void rd(T &x)
{
    #define gc getchar()
    x = 0;
    char c = gc;
    ll f = 1;
    while (!isdigit(c)) {if (c == '-') f = -1;c = gc;}
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = gc;
    x *= f;
    #undef gc
}
template <class T>
void pt(T x)
{
    if (x < 0)
        putchar ('-'), x = (~x) + 1;
    if (x > 9)
        pt(x / 10);
    putchar ((x % 10) ^ 48);
}
template <class T>
T Max(T x, T y)
{
    return x > y ? x : y;
}
template <class T>
T Min(T x, T y)
{
    return x < y ? x : y;
}
void openfile()
{
    freopen("sort.in", "r", stdin);
    freopen("sort.out", "w", stdout);
}
const int N = 1e5 + 5;
int n, m, a[N], q, l, r, fps;
bool bucket[N];
void low()
{
    int maxx = 0, tot = l;
    for (int i = l;i <= r; i++)
        bucket[a[i]] = 1, maxx = Max(maxx, a[i]);
    for (int i = maxx;i > 0; i--)
        if (bucket[i])
        {
            a[tot] = i;
            bucket[i] = 0;
            tot++;
            if (tot > r)
                break;
        }
}
void high()
{
    int minn = N, tot = l;
    for (int i = l;i <= r; i++)
        bucket[a[i]] = 1, minn = Min(minn, a[i]);
    for (int i = minn;i <= n; i++)
        if (bucket[i])
        {
            a[tot] = i;
            bucket[i] = 0;
            tot++;
            if (tot > r)
                break;
        }
}
int main()
{
    // openfile();
    rd(n), rd(m);
    for (int i = 1;i <= n; i++)
        rd(a[i]);
    while (m--)
    {
        rd(fps), rd(l), rd(r);
        if (fps)
            low();
        else
            high();
    }
    rd(q);
    pt(a[q]);
    return 0;
}

Thanks for reading!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值