BZOJ3585: mex

3585: mex

Time Limit: 20 Sec  Memory Limit: 128 MB

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

分析:莫队+权值分块;转移用莫队,查找分块sqrt(n)查;

   没有啥思维难度,大力码就行了。

代码:

#include <bits/stdc++.h>
const int maxn=2e5+10;
int n,m,k,t,tot,sz,sz1,a[maxn],d[maxn],bl[maxn],bs[maxn],cnta[maxn],cntb[maxn],num[maxn],ans[maxn];
using namespace std;
struct node
{
    int l,r,id;
    bool operator<(const node&p)const
    {
        return bl[l]==bl[p.l]?r<p.r:bl[l]<bl[p.l];
    }
}qu[maxn];
int main()
{
    int i,j;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)scanf("%d",&a[i]),d[++tot]=a[i];
    sort(d+1,d+tot+1);
    tot=unique(d+1,d+tot+1)-d-1;
    for(i=1;i<=n;i++)a[i]=lower_bound(d+1,d+tot+1,a[i])-d-1;
    if(d[1]!=0)tot=2;
    else
    {
        bool flag=false;
        for(i=2;i<=tot;i++)if(d[i]!=d[i-1]+1)
        {
            tot=d[i-1]+3;
            flag=true;
            break;
        }
        if(!flag)tot=tot+3;
    }
    for(i=1;i<=n;i++)if(d[a[i]+1]>tot-2)
    {
        a[i]=tot-1;
    }
    for(i=1;i<=m;i++)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        qu[i]=node{l,r,i};
    }
    sz=round(sqrt(n)+0.5);
    for(i=1;i<=n;i++)bl[i]=(i-1)/sz+1;
    sz1=round(sqrt(tot)+0.5);
    for(i=0;i<=tot-1;i++)bs[i]=i/sz1+1,num[bs[i]]++;
    sort(qu+1,qu+m+1);
    int l=1,r=0;
    for(i=1;i<=m;i++)
    {
        while(r<qu[i].r)
        {
            ++r;
            cnta[bs[a[r]]]+=(!cntb[a[r]]);
            ++cntb[a[r]];
        }
        while(l>qu[i].l)
        {
            --l;
            cnta[bs[a[l]]]+=(!cntb[a[l]]);
            ++cntb[a[l]];
        }
        while(l<qu[i].l)
        {
            --cntb[a[l]];
            cnta[bs[a[l]]]-=(!cntb[a[l]]);
            l++;
        }
        while(r>qu[i].r)
        {
            --cntb[a[r]];
            cnta[bs[a[r]]]-=(!cntb[a[r]]);
            r--;
        }
        for(j=1;;j++)
        {
            if(cnta[j]==num[j])continue;
            for(k=(j-1)*sz1;;k++)
            {
                if(cntb[k]==0)break;
            }
            break;
        }
        ans[qu[i].id]=k;
    }
    for(i=1;i<=m;i++)printf("%d\n",ans[i]);
    return 0;
}
/*
3 6
1 2 3
1 1
2 2
3 3
1 2
2 3
1 3
*/
posted @ 2017-11-23 22:01  mxzf0213  阅读(144)  评论(0编辑  收藏  举报