zoukankan      html  css  js  c++  java
  • bzoj 3585: mex

    3585: mex

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 969  Solved: 511
    [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

    以权值为下标,

    minn[i]=j,表示i所代表的权值为[l,r]的区间,最早出现的位置为j

    例:0 2 1 0 1 3 2

    对于root[7]来说,

    [0,3]=1, 0最早出现在第1个位置

    [1,3]=2, 2最早出现在第2个位置

    查询[l,r]时,在root[r]里查询

    如果左子区间的minn>=l,说明权值小的左边一半都最早出现在l以后,就往右孩子找

    否则,说明权值小的左边一半有没有出现在l之后的,就往左孩子找

    因为是在root[r]里,所以保证不超过右边界

    对于10^9的权值,离散化?

    不。

    如果权值>n,直接让它=n

    因为此时<n中一定有没有出现的数

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 200001
    using namespace std;
    int n,q,tot;
    int root[N],minn[N*20];
    
        int lc[N*20],rc[N*20];
        void change(int &now,int pre,int l,int r,int pos,int val)
        {
            if(!now) now=++tot;
            if(l==r) 
            {
                minn[now]=val;
                return;
            }
            int mid=l+r>>1;
            if(pos<=mid) 
            {
                change(lc[now],lc[pre],l,mid,pos,val);
                rc[now]=rc[pre];
            }
            else 
            {
                change(rc[now],rc[pre],mid+1,r,pos,val);
                lc[now]=lc[pre];
            }
            minn[now]=min(minn[lc[now]],minn[rc[now]]);
        }
        int query(int now,int l,int r,int pos)
        {
            if(l==r) return l;
            int mid=l+r>>1;
            if(minn[lc[now]]>=pos) return query(rc[now],mid+1,r,pos);
            return query(lc[now],l,mid,pos);
        }
    
    int main()
    {
        freopen("mex.in","r",stdin);
        freopen("mex.out","w",stdout);
        int m;
        scanf("%d%d",&n,&m);
        int x;
        for(int i=1;i<=n;i++) 
        {
            scanf("%d",&x);
            if(x>n) x=n;
            change(root[i],root[i-1],0,n,x,i);
        } 
        int l,r;
        while(m--)
        {
            scanf("%d%d",&l,&r);
            printf("%d
    ",query(root[r],0,n,l));
        }
    }
  • 相关阅读:
    常见浏览器的兼容问题以及解决方案 (仅供参考)
    了解浏览器如何工作—渲染引擎1
    维基百科公式不能正常显示
    IDL读取fits文件
    卷积,系统
    硬盘被占用无法拔出问题解决
    Faster RCNN 改进论文及资料
    Pycharm 使用问题一览
    java eclipse 使用随笔
    Images
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6914035.html
Copyright © 2011-2022 走看看