zoukankan      html  css  js  c++  java
  • Luogu 2824 [HEOI2016/TJOI2016]排序

    BZOJ 4552

    挺妙的解法。

    听说这题直接用一个桶能拿到$80 pts$

    发现如果是一个排列的话,要对这个序列排序并不好做,但是假如是$01$序列的话,要对一个区间排序还是很简单的。

    发现最后的询问其实只有一个,所以我们考虑二分这个答案(其实感觉在这题中答案的单调性并不是很明显),每一次二分得到一个$mid$,对于所有的$a_i$,我们把$a_i geq mid$的$i$都记为$1$,把所有$a_i < mid$的值都记为$0$,然后对于每一次排序,我们只要获取这个区间的$0$和$1$的个数,然后区间覆盖一下就可以了。

    区间覆盖,区间求和,岂不是线段树。

    这样子所有操作完成了之后,我们只要看一看原来询问的这个位置的数是不是$1$,如果是$1$,那么说明这里的数$geq mid$,移动左端点,否则移动右端点。

    答案的单调性在这个时候就显现出来了。

    这个思想值得借鉴。

    时间复杂度$O(nlog^2n)$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int N = 1e5 + 5;
    
    int n, m, K, a[N], b[N];
    
    struct Option {
        int type, x, y;
    } q[N];  
    
    inline void read(int &X) {
        X = 0; char ch = 0; int op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    namespace SegT {
        int s[N << 2], tag[N << 2];
        
        #define lc p << 1
        #define rc p << 1 | 1
        #define mid ((l + r) >> 1)
        
        inline void up(int p) {
            if(p) s[p] = s[lc] + s[rc];
        }
        
        inline void down(int p, int l, int r) {
            if(tag[p] == -1) return;
            s[lc] = tag[p] * (mid - l + 1), tag[lc] = tag[p];
            s[rc] = tag[p] * (r - mid), tag[rc] = tag[p];
            tag[p] = -1;
        }
        
        void build(int p, int l, int r) {
            tag[p] = -1;
            if(l == r) {
                s[p] = b[l];
                return;
            }
            
            build(lc, l, mid);
            build(rc, mid + 1, r);
            up(p);
        }
        
        void modify(int p, int l, int r, int x, int y, int v) {
            if(x <= l && y >= r) {
                s[p] = (r - l + 1) * v;
                tag[p] = v;
                return;
            }
            
            down(p, l, r);
            if(x <= mid) modify(lc, l, mid, x, y, v);
            if(y > mid) modify(rc, mid + 1, r, x, y, v);
            up(p);
        }
        
        int query(int p, int l, int r, int x, int y) {
            if(x <= l && y >= r) return s[p];
            
            down(p, l, r);
            
            int res = 0;
            if(x <= mid) res += query(lc, l, mid, x, y);
            if(y > mid) res += query(rc, mid + 1, r, x, y);
            return res;
        }
        
        #undef lc
        #undef rc
        #undef mid
        
    } using namespace SegT;
    
    inline bool chk(int mid) {
        for(int i = 1; i <= n; i++) 
            if(mid <= a[i]) b[i] = 1;
            else b[i] = 0;
        
        build(1, 1, n);
        for(int i = 1; i <= m; i++) {            
            int num1 = query(1, 1, n, q[i].x, q[i].y);
            int num0 = q[i].y - q[i].x + 1 - num1;
            if(!q[i].type) {
                if(num0) modify(1, 1, n, q[i].x, q[i].x + num0 - 1, 0);
                modify(1, 1, n, q[i].x + num0, q[i].y, 1); 
            } else {
                if(num1) modify(1, 1, n, q[i].x, q[i].x + num1 - 1, 1);
                modify(1, 1, n, q[i].x + num1, q[i].y, 0); 
            }  
        }
        
        int res = query(1, 1, n, K, K);
        return (res > 0);
    }
    
    int main() {
        read(n), read(m);
        for(int i = 1; i <= n; i++) read(a[i]);
        for(int i = 1; i <= m; i++)
            read(q[i].type), read(q[i].x), read(q[i].y);
        read(K);
        
        int ln = 1, rn = n, mid, res;
        for(; ln <= rn; ) {
            mid = (ln + rn) / 2;
            if(chk(mid)) ln = mid + 1, res = mid;
            else rn = mid - 1;
        }
        
        printf("%d
    ", res);
        return 0;
    }
    View Code
  • 相关阅读:
    真的是简单、简洁、简易、简明之道!!!
    HashMap源码解读
    Jenkins Pipeline
    C语言二级指针free|一级指针存储内存地址
    openjdk编译和调试,JVM编译调试
    java linux和win jdk安装包jdk1.6、jdk1.7和jdk1.8 7u80 8u181 8u161
    关于java代码打包成jar在控制台运行变慢的问题
    Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen
    mongodb副本集
    condition
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9703485.html
Copyright © 2011-2022 走看看