BZOJ3585: mex

题解: 权值分块 莫队查询即可

/**************************************************************
    Problem: 3585
    User: c20161007
    Language: C++
    Result: Accepted
    Time:6248 ms
    Memory:8340 kb
****************************************************************/
 
#include <bits/stdc++.h>
#define N 200005
#define INF 100000007
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}
int n,m,size,size1;
int p[N],a[N],c[N];
int vis[N],pp[N];int b[1005];
typedef struct node{
    int l,r,biao;
    friend bool operator <(node aa,node bb){
        if(p[aa.l]==p[bb.l]) return aa.r<bb.r;
        return p[aa.l]<p[bb.l];
    } 
}node;
node d[N];
int ans[N];
int main(){
    ios::sync_with_stdio(false);
    n=read();m=read();size=(int)sqrt(n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);p[i]=(i-1)/size+1;
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d",&d[i].l,&d[i].r);d[i].biao=i;
    }
    sort(d+1,d+m+1);size1=(int)sqrt(n+1);
    for(int i=1;i<=n+1;i++){
        pp[i]=(i-1)/size1+1;
    }
    for(int i=1;i<=pp[n+1];i++) b[i]=min(n+1,size1*i)-(size1*(i-1)+1)+1;
    int L=1;int R=0;
    for(int i=1;i<=m;i++){
        while(R>d[i].r){
            if(a[R]<=n){
                c[a[R]]--;
                if(c[a[R]]==0) b[pp[a[R]+1]]++;
            }
            R--;
        }
        while(R<d[i].r){
            R++;
            if(a[R]<=n){
                c[a[R]]++;
                if(c[a[R]]==1) b[pp[a[R]+1]]--;
            }
        }
        while(L<d[i].l){
            if(a[L]<=n){
                c[a[L]]--;
                if(c[a[L]]==0) b[pp[a[L]+1]]++;
            }
            L++;
        }
        while(L>d[i].l){
            L--;
            if(a[L]<=n){
                c[a[L]]++;
                if(c[a[L]]==1) b[pp[a[L]+1]]--;
            }
        }
        for(int j=1;j<=pp[n+1];j++){
            if(b[j]==0) continue;
            else{
                for(int k=size1*(j-1)+1;k<=min(n+1,size1*j);k++){
                    if(c[k-1]==0){
                        ans[d[i].biao]=k-1;
                        break;
                    }
                }
                break;
            }
        }
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

 

3585: mex

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1611  Solved: 809
[Submit][Status][Discuss]

Description

  有一个长度为n的数组{a1,a2,...,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。

Input

  第一行n,m。
  第二行为n个数。
  从第三行开始,每行一个询问l,r。

Output

  一行一个数,表示每个询问的答案。

Sample Input

5 5
2 1 0 2 1
3 3
2 3
2 4
1 2
3 5

Sample Output

1
2
3
0
3

HINT

数据规模和约定

  对于100%的数据:

  1<=n,m<=200000

  0<=ai<=109

  1<=l<=r<=n

 

  对于30%的数据:


  1<=n,m<=1000

posted @ 2018-08-19 21:08  wang9897  阅读(107)  评论(0编辑  收藏  举报