bzoj 4552

二分 + 线段树
二分一个值 x, 讲原序列转化为01序列
1表示该数>x, 0表示改数<x;
线段树维护区间和进行判断

#include <bits/stdc++.h>

const int N = 1e5 + 10;

#define gc getchar()

int n, m, Q;
int A[N], B[N];
int S[N << 2], W[N << 2], F[N << 2];
int opt[N], lask[N], rask[N];
int js;

inline int read() {
    int x = 0; char c = gc;
    while(c < '0' || c > '9') c = gc;
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
    return x;
}

#define lson jd << 1
#define rson jd << 1 | 1

void Build_size(int l, int r, int jd) {
    S[jd] = r - l + 1;
    if(l == r) return ;
    int mid = (l + r) >> 1;
    Build_size(l, mid, lson);
    Build_size(mid + 1, r, rson);
} 

void Build_tree(int l, int r, int jd) {
    F[jd] = -1;
    if(l == r) {W[jd] = B[l]; return ;}
    int mid = (l + r) >> 1;
    Build_tree(l, mid, lson);
    Build_tree(mid + 1, r, rson);
    W[jd] = W[lson] + W[rson];
}

void Down(int jd) {
    F[lson] = F[rson] = F[jd];
    W[lson] = S[lson] * F[jd], W[rson] = S[rson] * F[jd];
    F[jd] = -1;
}

int Answer;

void Sec_A(int l, int r, int jd, int x, int y) {
    if(x > y) return ;
    if(x <= l && r <= y) {Answer += W[jd]; return ;}
    if(F[jd] != -1) Down(jd);
    int mid = (l + r) >> 1;
    if(x <= mid) Sec_A(l, mid, lson, x, y);
    if(y > mid)  Sec_A(mid + 1, r, rson, x, y);
}

void Sec_G(int l, int r, int jd, int x, int y, int how) {
    if(x > y) return ; 
    if(x <= l && r <= y) {
        F[jd] = how;
        W[jd] = S[jd] * how;
        return ;
    }
    if(F[jd] != -1) Down(jd);
    int mid = (l + r) >> 1;
    if(x <= mid) Sec_G(l, mid, lson, x, y, how);
    if(y > mid)  Sec_G(mid + 1, r, rson, x, y, how);
    W[jd] = W[lson] + W[rson];
}

inline bool See(int x) {
    for(int i = 1; i <= n; i ++) B[i] = (A[i] >= x);
    Build_tree(1, n, 1);
    for(int i = 1; i <= m; i ++) {
        Answer = 0;
        Sec_A(1, n, 1, lask[i], rask[i]);
        int sum = Answer;
        if(!opt[i]) {
            Sec_G(1, n, 1, rask[i] - sum + 1, rask[i], 1);
            Sec_G(1, n, 1, lask[i], rask[i] - sum, 0);
        } else {
            Sec_G(1, n, 1, lask[i], lask[i] + sum - 1, 1);
            Sec_G(1, n, 1, lask[i] + sum, rask[i], 0);
        }
    }
    Answer = 0;
    Sec_A(1, n, 1, Q, Q);
    return Answer;
}

int main() {
    n = read(), m = read();
    for(int i = 1; i <= n; i ++) A[i] = read();
    for(int i = 1; i <= m; i ++) opt[i] = read(), lask[i] = read(), rask[i] = read();
    Q = read();
    Build_size(1, n, 1);
    int L = 1, R = n, Ans(0);
    while(L <= R) {
        int Mid = (L + R) >> 1;
        if(See(Mid)) L = Mid + 1, Ans = Mid;
        else R = Mid - 1;
    }
    std:: cout << Ans;
    return 0;
}

 

posted @ 2018-06-02 15:41  qmey  阅读(124)  评论(0编辑  收藏  举报