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 << "\n";
    return 0;
}

 

posted @ 2019-03-14 08:42  MJT12044  阅读(181)  评论(0编辑  收藏  举报