Several practices on the range of $ mex $

About the interval \ (mex \) several practices

Topic Link

Subject to the effect

In seeking \ (SG \) mentioned a function through a \ (MEX \) function;
\ (MEX (\ {a_i \}) \) represents the \ (A \) minimum natural number not appearing, where \ (a_i \ in \ N \) .

To a length \ (n-\) sequence \ (A \) , \ (m \) queries, each query \ (mex (\ {a_i \ }), i \ in [l, r] \)

1, Mo + team Fenwick tree

Fenwick tree to maintain each of the weights number of occurrences;
Complexity: \ (O (m \ sqrt n-logN) \)

2, Mo + team block

The weight sub-blocks, each block maintains the number appeared a few;
Complexity: $ O ((n + m ) \ sqrt n);
code as follows:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }

const int N = 2e5 + 5;

int blo, bl[N];

struct query {
    int l, r, id;
} q[N];
int n, m;
int a[N], res[N];

inline bool cmp (const query &i, const query &j) {
    if (bl[i.l] != bl[j.l])
        return bl[i.l] < bl[j.l];
    if (bl[i.l] & 1)
        return i.r < j.r;
    return i.r > j.r;
}

struct block_split {
    int a[N], b[1000];
    inline void modify(int p, int k) {
        if (!a[p])
            ++b[bl[p]];
        a[p] += k;
        if (!a[p])
            --b[bl[p]];
    }
    int query() {
        int i;
        for (i = 1; i < bl[n]; ++i)
            if (b[i] < blo)
                break;
        for (int j = (i - 1) * blo; j <= std::min(n, i * blo - 1); ++j)
            if (!a[j])
                return j;
        return n;
    }
} B;

inline void add(const int p) {
    B.modify(a[p], 1);
}

inline void rem(const int p) {
    B.modify(a[p], -1);
}

int main() {
    n = in(), m = in();
    for (int i = 1; i <= n; ++i)
        a[i] = in(), chk_min(a[i], n);
    for (int i = 1; i <= m; ++i)
        q[i] = (query){in(), in(), i};
    blo = (int)sqrt(n + 1);
    for (int i = 0; i <= n; ++i)
        bl[i] = i / blo + 1;
    std::sort(q + 1, q + 1 + m, cmp);
    for (int i = 1, l = 1, r = 0; i <= m; ++i) {
        for (; l > q[i].l; add(--l));
        for (; r < q[i].r; add(++r));
        for (; l < q[i].l; rem(l++));
        for (; r > q[i].r; rem(r--));
        res[q[i].id] = B.query();
    }
    for (int i = 1; i <= m; ++i)
        printf("%d\n", res[i]);
    return 0;
}

3, the Chairman of the tree

The above approach to offline, Chairman of the tree can handle online inquiries, and the complexity of the more outstanding.
Chairman of the tree maintenance each number in the first \ (i \) position before a version of history, the last occurrence.
For a set of query \ (L, r \) , the first \ (r \) to find the last time in the history of th edition \ (l \) the minimum number of pre-historic version.
code show as below:

#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
    int x = 0; char c = getchar();
    while (c < '0' || c > '9')
        c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x;
}

const int N = 2e5 + 5;

struct persistable_tree {
    int min[20 * N], rt[20 * N], c[20 * N][2];
    int tot;

    void modify(int pos, int k, int tl, int tr, int pre, int &p) {
        p = ++tot;
        if (tl == tr)
            return (void)(min[p] = k);
        c[p][0] = c[pre][0], c[p][1] = c[pre][1];
        int mid = (tl + tr) >> 1;
        if (mid >= pos)
            modify(pos, k, tl, mid, c[pre][0], c[p][0]);
        else
            modify(pos, k, mid + 1, tr, c[pre][1], c[p][1]);
        min[p] = std::min(min[c[p][0]], min[c[p][1]]);
    }

    int query(int k, int tl, int tr, int p) {
        if (tl == tr)
            return tl;
        int mid = (tl + tr) >> 1;
        if (min[c[p][0]] < k)
            return query(k, tl, mid, c[p][0]);
        else
            return query(k, mid + 1, tr, c[p][1]);
    }
} T;

int main() {
    int n = in(), m = in();
    for (int i = 1, x; i <= n; ++i) {
        x = in();
        T.modify(x, i, 0, n, T.rt[i - 1], T.rt[i]);
    }
    int l, r;
    while (m--) {
        l = in(), r = in();
        printf("%d\n", T.query(l, 0, n, T.rt[r]));
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/15owzLy1-yiylcy/p/10983951.html