zoukankan      html  css  js  c++  java
  • bzoj3585 mex

    3585: mex

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

    分析:和spoj DQUERY以及bzoj2653类似.都是主席树的妙用.

       因为要求mex,每棵主席树内部维护的肯定是权值,维护权值的什么呢? 对于一个区间[l,r], 假设已经固定了右端点r,那么只需要保证左端点即可.当主席树处理到权值区间[x,y]时,如果[x,mid]都在l右边,那么mex肯定只会出现在[mid+1,y]中,否则就会出现在[x,mid]中. 那么第i棵主席树维护的就是下标区间[1,i]中权值的最左位置. 像线段树一样处理.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 200010;
    int n,m,root[maxn],tot;
    
    struct node
    {
        int left,right,minn;
    }e[maxn * 40];
    
    void build(int &o,int l,int r)
    {
        o = ++tot;
        e[o].minn = 0;
        if (l == r)
            return;
        int mid = (l + r) >> 1;
        build(e[o].left,l,mid);
        build(e[o].right,mid + 1,r);
    }
    
    void pushup(int o)
    {
        int temp = 0x7fffffff;
        if (e[o].left)
            temp = min(e[e[o].left].minn,temp);
        if (e[o].right)
            temp = min(e[e[o].right].minn,temp);
        e[o].minn = temp;
    }
    
    void update(int l,int r,int x,int &y,int pos,int v)
    {
        e[y = ++tot] = e[x];
        if (l == r)
        {
            e[y].minn = v;
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid)
            update(l,mid,e[x].left,e[y].left,pos,v);
        else
            update(mid + 1,r,e[x].right,e[y].right,pos,v);
        pushup(y);
    }
    
    int query(int l,int r,int x,int y)
    {
        if (l == r)
            return l;
        int mid = (l + r) >> 1;
        if (e[e[y].left].minn >= x)
            return query(mid + 1,r,x,e[y].right);
        else
            return query(l,mid,x,e[y].left);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        build(root[0],0,n);
        for (int i = 1; i <= n; i++)
        {
            int x;
            scanf("%d",&x);
            if (x >= n)
                x = n;
            update(0,n,root[i - 1],root[i],x,i);
        }
        for (int i = 1; i <= m; i++)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d
    ",query(0,n,l,root[r]));
        }
    
        return 0;
    }

     

  • 相关阅读:
    移动前端开发之viewport的深入理解
    javascript的事件监听与捕获和冒泡
    AngularJS服务中serivce,factory,provider的区别
    使用shadow dom封装web组件
    Web Components之Custom Elements
    javascript 布尔类型值判断
    requestAnimationFrame()
    二十周年感言
    文件上传实例
    jhipster技术栈研究
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8721689.html
Copyright © 2011-2022 走看看