BZOJ 3585 mex

题目已经没有了

思路:

莫队+分块

首先有一个结论:所有的答案都在0到n之间,用反正法就能证明,所以所有大于n的数都可以看成n

离线,对询问区间进行莫队,再对答案的范围0到n进行分块

复杂度(n+2*m)√n

代码:

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 2e5 + 5;
int a[N], cnt[N], bl[N], ans[N], l[555], r[555], block[555], blo, n;
struct node {
    int l, r, bl, id;
    bool operator < (const node & t) const {
        if(bl == t.bl) return r < t.r;
        else bl < t.bl;
    }
}Q[N];
void add(int x) {
    if(!cnt[x]) block[bl[x]]++;
    cnt[x] ++;
}
void del(int x) {
    cnt[x]--;
    if(!cnt[x]) block[bl[x]]--;
}
int query() {
    int i;
    for (i = bl[0]; i <= bl[n]; i++) if(block[i] != r[i] - l[i] + 1) break;
    for (int j = l[i]; j <= r[i]; j++) if(!cnt[j]) return j;
}
int main() {
    int m;
    while(~scanf("%d%d", &n, &m)) {
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            if(a[i] >= n) a[i] = n;
        }
        blo = sqrt(n+1);
        for (int i = 0; i <= n; i++) bl[i] = i/blo + 1;
        for (int i = bl[0]; i <= bl[n]; i++) {
            l[i] = (i-1)*blo;
            r[i] = min(i*blo-1, n);
        }
        blo = sqrt(n);
        for (int i = 1; i <= m; i++) {
            scanf("%d%d", &Q[i].l, &Q[i].r);
            Q[i].bl = (Q[i].l - 1)/blo + 1;
            Q[i].id = i;
        }
        sort(Q+1, Q+1+m);
        mem(cnt, 0);
        mem(block, 0);
        int l = 1, r = 0;
        for (int i = 1; i <= m; i++) {
            while(l > Q[i].l) add(a[--l]);
            while(r < Q[i].r) add(a[++r]);
            while(r > Q[i].r) del(a[r--]);
            while(l < Q[i].l) del(a[l++]);
            ans[Q[i].id] = query();
        }
        for (int i = 1; i <= m; i++) printf("%d\n", ans[i]);
    }
    return 0;
}

 

posted @ 2018-05-31 15:55  Wisdom+.+  阅读(228)  评论(0编辑  收藏  举报