BZOJ4552 (binary segment tree +)

Points

  • N different sequence of numbers, one strategy is to answer the newly acquired half of this position can then be adjusted up and down.
  • Magically mid focus only larger or smaller than 0,1 and assignment, so that sorting operations of m can be maintained with a segment tree!
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 1e5 + 5;
int n, m, a[maxn], op[maxn], L[maxn], R[maxn], question;

class SegmentTree {
public:
    #define ls(p) p << 1
    #define rs(p) p << 1 | 1

    struct Node {
        int l, r, sum, tag;
    }t[maxn * 3];

    void Push_up(int p) {
        t[p].sum = t[ls(p)].sum + t[rs(p)].sum;
    }

    void Change(int son, int fa) {
        t[son].tag = t[fa].tag;
        t[son].sum = t[fa].tag * (t[son].r - t[son].l + 1);
    }

    void Push_down(int p) {
        if (t[p].tag < 0)   return;
        Change(ls(p), p), Change(rs(p), p);
        t[p].tag = -1;
    }

    void Build(int l, int r, int p, int val) {
        t[p].l = l, t[p].r = r, t[p].tag = -1;
        if (l == r) {
            t[p].sum = a[l] >= val;
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, ls(p), val);
        Build(mid + 1, r, rs(p), val);
        Push_up(p);
    }

    void Modify(int l, int r, int p, int k) {
        if (l <= t[p].l && t[p].r <= r) {
            t[p].tag = k;
            t[p].sum = k * (t[p].r - t[p].l + 1);
            return;
        }
        Push_down(p);
        int mid = (t[p].l + t[p].r) >> 1;
        if (l <= mid)   Modify(l, r, ls(p), k);
        if (mid < r)    Modify(l, r, rs(p), k);
        Push_up(p);
    }

    int Query(int l, int r, int p) {
        if (l <= t[p].l && t[p].r <= r) return t[p].sum;
        Push_down(p);
        int mid = (t[p].l + t[p].r) >> 1;
        if (l > mid)    return Query(l, r, rs(p));
        if (r <= mid)   return Query(l, r, ls(p));
        return Query(l, r, ls(p)) + Query(l, r, rs(p));
    }
};

bool OK(int mid) {
    SegmentTree tree;
    tree.Build(1, n, 1, mid);
    for (int i = 1; i <= m; i++) {
        int val = tree.Query(L[i], R[i], 1);
        if (val == 0 || val == R[i] - L[i] + 1) continue;
        if (op[i]) {
            tree.Modify(L[i], L[i] + val - 1, 1, 1);
            tree.Modify(L[i] + val, R[i], 1, 0);
        } else {
            tree.Modify(R[i] - val + 1, R[i], 1, 1);
            tree.Modify(L[i], R[i] - val, 1, 0);
        }
    }
    return tree.Query(question, question, 1) == 1;
}

int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    for (int i = 1; i <= m; i++)
        scanf("%d %d %d", &op[i], &L[i], &R[i]);
    scanf("%d", &question);

    int l = 1, r = n, ans;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (OK(mid))    ans = mid, l = mid + 1;
        else    r = mid - 1;
    }

    return !printf("%d\n", ans);
}

Guess you like

Origin www.cnblogs.com/AlphaWA/p/10988387.html