zoukankan      html  css  js  c++  java
  • 莫队 mex

    问题 G: mex
    时间限制: 2 Sec 内存限制: 128 MB
    题目描述
      有一个长度为n的数组{a1,a2,…,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。

      第一行n,m。
      第二行为n个数。
      从第三行开始,每行一个询问l,r。
    输出
      一行一个数,表示每个询问的答案。
    样例输入
    5 5
    2 1 0 2 1
    3 3
    2 3
    2 4
    1 2
    3 5
    样例输出
    1
    2
    3
    0
    3
    提示
    数据规模和约定
      对于100%的数据:
      1<=n,m<=200000
      0<=ai<=109
      1<=l<=r<=n
      对于30%的数据:
      1<=n,m<=1000

    第一次做到这种暴力套暴力的题。。莫队套分块。
    最开始我想把答案在左右端点推移时就修改,发现太麻烦,反而更慢。
    那么以数为块,把所有数加一,就排除了0的情况,最后减回来即可。而且数组不需要开太大,到n即可。因为如果出现>n的数一定不符合。
    只是修改分块,记录下这个块有多少个数出现过,最后正大光明地找到第一个不全出现的块,枚举即可。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #define N 201000
    using namespace std;
    struct Q{int l,r,id;}q[N];
    int n,m,h,a[N],sum[N],kuai[N],ans[N];
    int b[N],shu[1000];
    inline bool cmp(Q a,Q b){return kuai[a.l]==kuai[b.l]?a.r<b.r:kuai[a.l]<kuai[b.l];}
    int main()
    {
        scanf("%d%d",&n,&m);h=sqrt(n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]++,kuai[i]=(i-1)/h+1;
        for(int i=1;i<=m;i++)scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
        sort(q+1,q+m+1,cmp);
        int l=0,r=0;
        for(int i=1;i<=m;i++)
        {
            for(;l<q[i].l;l++)
            {
                if(a[l]>=n)continue;
                sum[a[l]]--;
                if(sum[a[l]]==0)shu[kuai[a[l]]]--;
            }
            for(;l>q[i].l;l--)
            {
                if(a[l-1]>=n)continue;
                if(sum[a[l-1]]==0)shu[kuai[a[l-1]]]++;
                sum[a[l-1]]++;
            }
            for(;r<q[i].r;r++)
            {
                if(a[r+1]>=n)continue;
                if(sum[a[r+1]]==0)shu[kuai[a[r+1]]]++;
                sum[a[r+1]]++;
    
            }
            for(;r>q[i].r;r--)
            {
                if(a[r]>=n)continue;
                sum[a[r]]--;    
                if(sum[a[r]]==0)shu[kuai[a[r]]]--;
            }
            for(int k=1;k<=kuai[n];k++)
                if(shu[k]!=h)
                {
                    for(int j=(k-1)*h+1;j<=min(n,k*h);j++)
                        if(!sum[j]){ans[q[i].id]=j;break;}
                    break;
                }
        }
        for(int i=1;i<=m;i++)printf("%d
    ",ans[i]-1);
    }
  • 相关阅读:
    SimpleXML简单使用
    制作RSS供应源
    DOM方式操作XML
    Referer与图片防盗链
    PAT
    Margarite and the best present
    Petya and Origami
    Margarite and the best present
    Petya and Origami
    A/B
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632659.html
Copyright © 2011-2022 走看看