【CF 817F】MEX Queries(线段树)

Description

维护一个长度 1018 10 18 01 01 序列,要求兹瓷区间赋值、区间取反、查询第一个 0 0 的位置。


Solution

离散化后用线段树维护一个取反标记、一个赋值标记即可。


Code

/************************************************
 * Au: Hany01
 * Date: Aug 2nd, 2018
 * Prob: CF817 F
 * Email: [email protected]
 * Inst: Yali High School
************************************************/

#include

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia

template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

template <typename T> inline T read() {
    static T _, __; static char c_;
    for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
    for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
    return _ * __;
}

const int maxn = 1e5 + 5;

struct Op { int ty; LL l, r; }op[maxn];

LL ls[maxn << 2];
int co[maxn * 50], n, tag[maxn * 50], N, sv[maxn * 50];

#define mid ((l + r) >> 1)
#define lc (t << 1)
#define rc (lc | 1)

inline void maintain(int t) {
    if (co[lc] == co[rc]) co[t] = co[lc]; else co[t] = -1;
}

inline void rev(int t) {
    if (sv[t] >= 0) {
        sv[t] ^= 1, co[t] ^= 1;
    } else {
        tag[t] ^= 1;
        if (co[t] >= 0) co[t] ^= 1;
    }
}

inline void pushdown(int t) {
    if (sv[t] >= 0) {
        sv[lc] = sv[rc] = co[lc] = co[rc] = sv[t];
        tag[lc] = tag[rc] = 0;//!!!!!
        sv[t] = -1;
    }
    if (tag[t]) {
        tag[t] = 0;
        rev(lc), rev(rc);
    }
}

void build(int t, int l, int r) {
    sv[t] = -1;
    if (l != r) build(lc, l, mid), build(rc, mid + 1, r);
}

void update1(int t, int l, int r, int x, int y, int c) {
    if (x <= l && r <= y) { co[t] = sv[t] = c, tag[t] = 0; return; }
    pushdown(t);
    if (x <= mid) update1(lc, l, mid, x, y, c);
    if (y >  mid) update1(rc, mid + 1, r, x, y, c);
    maintain(t);
}

void update2(int t, int l, int r, int x, int y) {
    if (x <= l && r <= y) { rev(t); return; }
    pushdown(t);
    if (x <= mid) update2(lc, l, mid, x, y);
    if (y >  mid) update2(rc, mid + 1, r, x, y);
    maintain(t);
}

int query(int t, int l, int r) {
    if (co[t] == 0 || !t) return l;
    pushdown(t);
    if (co[lc] == 1) return query(rc, mid + 1, r);
    return query(lc, l, mid);
}

int main()
{
#ifdef hany01
    freopen("cf817f.in", "r", stdin);
    freopen("cf817f.out", "w", stdout);
#endif

    n = read<int>(), ls[N = 1] = 1;
    For(i, 1, n) {
        op[i] = Op{read<int>(), read(), read()};
        ls[++ N] = op[i].l, ls[++ N] = op[i].r;
        ls[++ N] = op[i].r + 1;
        ls[++ N] = op[i].l + 1;
    }

    sort(ls + 1, ls + 1 + N), N = unique(ls + 1, ls + 1 + N) - ls - 1;
    build(1, 1, N);
    For(i, 1, n) {
        if (op[i].ty < 3)
            update1(1, 1, N, lower_bound(ls + 1, ls + 1 + N, op[i].l) - ls, lower_bound(ls + 1, ls + 1 + N, op[i].r) - ls, op[i].ty & 1);
        else
            update2(1, 1, N, lower_bound(ls + 1, ls + 1 + N, op[i].l) - ls, lower_bound(ls + 1, ls + 1 + N, op[i].r) - ls);
        printf("%lld\n", ls[query(1, 1, N)]);
    }

    return 0;
}

你可能感兴趣的:(Codeforces,线段树)