• [Luogu2824] [HEOI2016/TJOI2016]排序


    题目描述

    在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q位置上的数字。

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    6 3
    1 6 2 5 3 4
    0 1 4
    1 3 6
    0 2 4
    3
    输出样例#1: 复制
    5

    说明

    河北省选2016第一天第二题。原题的时限为6s,但是洛谷上是1s,所以洛谷的数据中,对于30%的数据,有 n,m<=1000,对于100%的数据,有 n,m<=30000


    二分答案的大小mid。

    大于等于mid设为1,其余的设为0.

    这样可以用线段树实现$large O(logN)$排序。

    这样排序结束之后如果位置p是1, 就增大l, 否则减小r。


    #include <iostream>
    #include <cstdio>
    using namespace std;
    #define reg register
    inline int read() {
        int res = 0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar();
        return res;
    }
    #define N 100010
    
    int n, m, p, erf;
    int ans;
    int a[N]; 
    struct Que {
        int l, r, opt;
    }q[N];
    int cnt[N*4], lazy[N*4];
    #define ls(o) o << 1
    #define rs(o) o << 1 | 1
    inline void pushup(int o)
    {
        cnt[o] = cnt[ls(o)] + cnt[rs(o)];
    }
    
    void Build(int l, int r, int o) 
    {
        lazy[o] = -1;
        if (l == r) 
        {
            cnt[o] = (a[l] >= erf);
            lazy[o] = -1;
            return ;
        }
        int mid = l + r >> 1;
        Build(l, mid, ls(o));
        Build(mid + 1, r, rs(o));
        pushup(o);
    }
    //lazy : 1) -1 means none
    // 2) 1 means change to 1
    // 3) 0 means change to 0
    inline void pushdown(int l, int r, int o) 
    {
        if (lazy[o] == -1) return ;
        int mid = l + r >> 1;
        if (lazy[o] == 1) {
            cnt[ls(o)] = mid - l + 1;
            lazy[ls(o)] = 1;
            
            cnt[rs(o)] = r - mid;
            lazy[rs(o)] = 1;
            
            lazy[o] = -1;
        } else {
            cnt[ls(o)] = 0, lazy[ls(o)] = 0;
            cnt[rs(o)] = 0, lazy[rs(o)] = 0;
            lazy[o] = -1;
        }
    }
    
    void change(int l, int r, int o, int ql, int qr, int c)
    {
        if (l >= ql and r <= qr) {
            if (c) cnt[o] = r - l + 1, lazy[o] = 1;
            else cnt[o] = 0, lazy[o] = 0;    
            return; 
        }
        pushdown(l, r, o);
        int mid = l + r >> 1;
        if (ql <= mid) change(l, mid, ls(o), ql, qr, c);
        if (qr > mid) change(mid + 1, r, rs(o), ql, qr, c);
        pushup(o);
    }
    
    int query(int l, int r, int o, int ql, int qr)
    {
        if (l >= ql and r <= qr) return cnt[o];
        pushdown(l, r, o);
        int mid = l + r >> 1;
        int res = 0;
        if (mid >= ql) res += query(l, mid, ls(o), ql, qr);
        if (mid < qr) res += query(mid + 1, r, rs(o), ql, qr);
        return res;
    }
    
    inline bool check(int mid) 
    {
        erf = mid;
        Build(1, n, 1);
    //    printf("mid = %d
    ", mid);
        for (reg int i = 1 ; i <= m ; i ++)
        {
            int L = q[i].l, R = q[i].r;
            int c = query(1, n, 1, L, R);
            if (q[i].opt == 0) { //升序 
                change(1, n, 1, R - c + 1, R, 1);
                change(1, n, 1, L, R - c, 0);
            } else {
                change(1, n, 1, L, L + c - 1, 1);
                change(1, n, 1, L + c, R, 0);
            }
        }
    //    printf("%d
    ", query(1, n, 1, p, p));
        return query(1, n, 1, p, p);
    }
    
    int main()
    {
        n = read(), m = read();
        for (reg int i = 1 ; i <= n ; i ++) a[i] = read();
        for (reg int i = 1 ; i <= m ; i ++) q[i].opt = read(), q[i].l = read(), q[i].r = read();
        p = read();
        int l = 1, r = n;
        while (l <= r) 
        {
            int mid = l + r >> 1;
            if (check(mid)) ans = mid, l = mid + 1;
            else r = mid - 1;
        }
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    假设客车的座位数是9行4列,使用二维数组在控制台应用程序中实现简单的客车售票系统。
    用lua求两个数组的交集、并集和补集。
    Lua 将数组中的某些value设置为nil,打印#数组的长度遇到的问题。
    用Lua编写ACM算法竞赛开灯问题
    EXCEL基础
    微服务的服务粒度该如何权衡
    Linux装cudnn
    How To Install Jenkins on Ubuntu 20.04
    获取heidisql保存的密码
    Spring Framework 远程命令执行漏洞复现(CVE202222965)
  • 原文地址:https://www.cnblogs.com/BriMon/p/9594106.html
Copyright © 2020-2023  润新知