zoukankan      html  css  js  c++  java
  • 4552: [Tjoi2016&Heoi2016]排序

    4552: [Tjoi2016&Heoi2016]排序

    链接

    分析:

      因为只询问一次,所以考虑二分这个数。显然是没有单调性的,但是我们可以二分所有大于等于mid的数中,是否有满足条件的x(而不是之间判断mid是否满足条件)。

      那么将大于等于mid的数设为1,小于mid的数设为0,此时对区间排序就变得非常简单了,只需要线段树求一下区间内1的个数,给一段区间赋值即可。

      最后判断询问的位置是否是1,如果是1,说明这个数是大于等于mid的,否者是小于mid的。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 100005;
    struct OPT { int opt, a, b; } Q[N];
    int a[N], b[N], n, m, k;
    
    struct SegmentTree{
        int sum[N << 2], tag[N << 2];
        void pushdown(int rt,int len) {
            sum[rt << 1] = tag[rt] * (len - (len >> 1)), tag[rt << 1] = tag[rt];
            sum[rt << 1 | 1] = tag[rt] * (len >> 1), tag[rt << 1 | 1] = tag[rt];
            tag[rt] = -1;
        }
        void build(int l,int r,int rt) {
            tag[rt] = -1;
            if (l == r) { sum[rt] = b[l]; return ; }
            int mid = (l + r) >> 1;
            build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1);
            sum[rt] = sum[rt << 1]  + sum[rt << 1 | 1];
        }
        void update(int l,int r,int rt,int L,int R,int v) {
            if (L > R) return ;
            if (L <= l && r <= R) { tag[rt] = v, sum[rt] = v * (r - l + 1); return ; }
            if (tag[rt] != -1) pushdown(rt, r - l + 1);
            int mid = (l + r) >> 1;
            if (L <= mid) update(l, mid, rt << 1, L, R, v);
            if (R > mid) update(mid + 1, r, rt << 1 | 1, L, R, v);
            sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
        }
        int query(int l,int r,int rt,int L,int R) {
            if (L <= l && r <= R) return sum[rt];
            if (tag[rt] != -1) pushdown(rt, r - l + 1);
            int mid = (l + r) >> 1, res = 0;
            if (L <= mid) res = query(l, mid, rt << 1, L, R);
            if (R > mid) res += query(mid + 1, r, rt << 1 | 1, L, R);
            return res;
        }
    }T;
    
    bool check(int x) {
        for (int i = 1; i <= n; ++i) b[i] = a[i] >= x;
        T.build(1, n, 1);
        for (int i = 1; i <= m; ++i) {
            int cnt = T.query(1, n, 1, Q[i].a, Q[i].b); 
            if (Q[i].opt) {
                T.update(1, n, 1, Q[i].a, Q[i].a + cnt - 1, 1);
                T.update(1, n, 1, Q[i].a + cnt, Q[i].b, 0);
            } else {
                T.update(1, n, 1, Q[i].a, Q[i].b - cnt, 0);
                T.update(1, n, 1, Q[i].b - cnt + 1, Q[i].b, 1);            
            }
        }
        return T.query(1, n, 1, k, k);
    }
    
    int main() {
        n = read(), m = read();
        for (int i = 1; i <= n; ++i) a[i] = read();
        for (int i = 1; i <= m; ++i) 
            Q[i].opt = read(), Q[i].a = read(), Q[i].b = read();
        k = read();
        int l = 1, r = n, ans = 0;
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (check(mid)) ans = mid, l = mid + 1;
            else r = mid - 1;
        }
        cout << ans << "
    ";
        return 0;
    }
  • 相关阅读:
    POJ 3687 Labeling Balls()
    POJ 2777 Count Color(线段树之成段更新)
    POJ 1961 Period( KMP )*
    POJ 2406 Power Strings (KMP)
    hdu 2199 Can you solve this equation?(二分搜索)
    10679 多少个1
    POJ 2823 Sliding Window
    POJ 2299 Ultra-QuickSort(线段树入门)
    最短路径—Dijkstra算法和Floyd算法
    poj1125&zoj1082Stockbroker Grapevine(Floyd算法)
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10527939.html
Copyright © 2011-2022 走看看