[BZOJ3685]普通van Emde Boas树 题解

[BZOJ3685]普通van Emde Boas树 题解

题目地址:BZOJ:Problem 3685. — 普通van Emde Boas树

题目描述

设计数据结构支持:
1 x 若x不存在,插入x
2 x 若x存在,删除x
3 输出当前最小值,若不存在输出-1
4 输出当前最大值,若不存在输出-1
5 x 输出x的前驱,若不存在输出-1
6 x 输出x的后继,若不存在输出-1
7 x 若x存在,输出1,否则输出-1

输入输出格式

输入格式:
第一行给出n,m 表示出现数的范围和操作个数
接下来m行给出操作
n<=10^6,m<=2*10^6,0<=x<n

输出格式:

输入输出样例

输入样例#1:

10 11
1 1
1 2
1 3
7 1
7 4
2 1
3
2 3
4
5 3
6 2

输出样例#1:

1
-1
2
2
2
-1

题解

虽说是vEB树的题,好像可以用权值线段树水过去,反正复杂度都是$O(n \log n)$。这里用了一个比较tricky的写法,把全局最大最小和前驱后继合并到一起,写成查区间最大最小了。

代码

// Code by KSkun, 2018/7
#include <cstdio>
#include <cctype>
#include <cstring>

#include <algorithm>

typedef long long LL;

inline char fgc() {
    static char buf[100000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
        ? EOF : *p1++;
}

inline LL readint() {
    register LL res = 0, neg = 1; register char c = fgc();
    for(; !isdigit(c); c = fgc()) if(c == '-') neg = -1;
    for(; isdigit(c); c = fgc()) res = (res << 1) + (res << 3) + c - '0';
    return res * neg;
}

const int MAXN = 1000005;

int has[MAXN];

#define lch o << 1
#define rch o << 1 | 1
#define mid ((l + r) >> 1)

int sgt[MAXN << 2];

inline void insert(int o, int l, int r, int x) {
    if(l == r) {
        sgt[o] = 1; return;
    }
    if(x <= mid) insert(lch, l, mid, x);
    else insert(rch, mid + 1, r, x);
    sgt[o] = sgt[lch] + sgt[rch];
}

inline void erase(int o, int l, int r, int x) {
    if(l == r) {
        sgt[o] = 0; return;
    }
    if(x <= mid) erase(lch, l, mid, x);
    else erase(rch, mid + 1, r, x);
    sgt[o] = sgt[lch] + sgt[rch];
}

// [0, x)
inline int querymx(int o, int l, int r, int x) {
    if(l == r) return sgt[o] && l != x ? l : -1;
    if(x <= mid) {
        return querymx(lch, l, mid, x);
    } else if(x <= r) {
        int res = querymx(rch, mid + 1, r, x);
        return res == -1 ? querymx(lch, l, mid, x) : res;
    } else {
        if(sgt[rch]) return querymx(rch, mid + 1, r, x);
        else return querymx(lch, l, mid, x);
    }
}

// (x, inf)
inline int querymn(int o, int l, int r, int x) {
    if(l == r) return sgt[o] && l != x ? l : -1;
    if(x > mid) {
        return querymn(rch, mid + 1, r, x);
    } else if(x >= l) {
        int res = querymn(lch, l, mid, x);
        return res == -1 ? querymn(rch, mid + 1, r, x) : res;
    } else {
        if(sgt[lch]) return querymn(lch, l, mid, x);
        else return querymn(rch, mid + 1, r, x);
    }
}

int n, m;

int main() {
    memset(has, -1, sizeof(has));
    n = readint(); m = readint();
    while(m--) {
        int op, x;
        op = readint();
        if(op != 3 && op != 4) x = readint();
        if(op == 1) {
            has[x] = 1;
            insert(1, 0, n - 1, x);
        } else if(op == 2) {
            has[x] = -1;
            erase(1, 0, n - 1, x);
        } else if(op == 3) {
            printf("%d\n", querymn(1, 0, n - 1, -1));
        } else if(op == 4) {
            printf("%d\n", querymx(1, 0, n - 1, n));
        } else if(op == 5) {
            printf("%d\n", querymx(1, 0, n - 1, x));
        } else if(op == 6) {
            printf("%d\n", querymn(1, 0, n - 1, x));
        } else {
            printf("%d\n", has[x]);
        }
    }
    return 0;
}


发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据