zoukankan      html  css  js  c++  java
  • p4137 Rmq Problem / mex

    传送门

    题目

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

    输入格式:

    第一行n,m。

    第二行为n个数。

    从第三行开始,每行一个询问l,r。

    输出格式:

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

    分析

    就是一个朴素的莫队题,虽然这个做法复杂度有问题(雾,但是能水过。注意mex肯定小于等于n,所以大于n的数没有意义,无需考虑。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    inline int read(){
          int x=0,f=1;char s=getchar();
          while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
          while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s-'0');s=getchar();}
          return f*x;
    }
    struct node{
          int l,r,no;
    }q[210000];
    int belong[210000],L[210000],R[210000],sum,block,a[210000];
    inline bool cmp(const node &x,const node &y){
          if(belong[x.l]==belong[y.l])return x.r<y.r;
          return belong[x.l]<belong[y.l];
    }
    int used[210000],n,mex,ans[210000],cnt;
    inline void add(int x){
          if(a[x]>n)return;
          used[a[x]]++;
          if(a[x]==mex){
              for(int i=a[x]+1;i<=n;i++)
                 if(!used[i]){
                 mex=i;
                 break;
               }
          }
    }
    inline void del(int x){
          if(x>n)return;
          used[a[x]]--;
          if(used[a[x]]<=0&&a[x]<mex)mex=a[x];
    }
    int main()
    {     int m,i,j,k;
          n=read(),m=read();
          for(i=1;i<=n;i++)a[i]=read();
          for(i=1;i<=m;i++)q[i].l=read(),q[i].r=read(),q[i].no=i;
          block=sqrt(n);
          sum=n%block==0?n/block:n/block+1;
          for(i=1;i<=n;i++)
             belong[i]=(i-1)/block+1;
          for(i=1;i<=sum;i++)
             L[i]=R[i-1]+1,R[i]=R[i-1]+block;
          R[sum]=n;
          sort(q+1,q+m+1,cmp);
          int le=1,ri=0;
          for(i=1;i<=m;i++){
               while(ri<q[i].r){
                   ri++;
                   add(ri);
               }
               while(ri>q[i].r){
                   del(ri);
                   ri--;
               }
               while(le<q[i].l){
                   del(le);
                   le++;
               }
               while(le>q[i].l){
                   le--;
                   add(le);
               }
               ans[q[i].no]=mex;
          }
          for(i=1;i<=m;i++)printf("%d
    ",ans[i]);
          return 0;
    }
  • 相关阅读:
    网络协议 22
    网络协议 21
    网络协议 20
    网络协议 19
    网络协议 18
    网络协议 17
    网络协议 16
    网络协议 15
    网络协议 14
    .net 4.0 中的特性总结(五):并行编程
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9192131.html
Copyright © 2011-2022 走看看