zoukankan      html  css  js  c++  java
  • 洛谷 P4137 Rmq Problem /mex 解题报告

    P4137 Rmq Problem /mex

    题意

    给一个长为(n(le 10^5))的数列({a}),有(m(le 10^5))个询问,每次询问区间的(mex)


    可以莫队然后对值域分块,这样求(mex)的复杂度就正确了

    一种更优的做法是按值域建可持久化线段树,对每个节点维护当前值域区间的最小出现位置,然后查询的时候就从(r)的那棵树一直尽量往左边走就好了


    Code:

    #include <cstdio>
    #include <cstring>
    const int N=2e5+10;
    #define ls ch[now][0]
    #define rs ch[now][1]
    #define ols ch[las][0]
    #define ors ch[las][1]
    int mi[N*30],ch[N*30][2],root[N],n,m,tot;
    int min(int x,int y){return x<y?x:y;}
    void rebuild(int las,int &now,int l,int r,int p,int d)
    {
        now=++tot;
        if(l==r){mi[now]=d;return;}
        int mid=l+r>>1;
        if(p<=mid) rebuild(ols,ls,l,mid,p,d),rs=ors;
        else ls=ols,rebuild(ors,rs,mid+1,r,p,d);
        mi[now]=min(mi[ls],mi[rs]);
    }
    int query(int now,int l,int r,int lim)
    {
        if(l==r) return l;
        int mid=l+r>>1;
        if(mi[ls]<lim) return query(ls,l,mid,lim);
        else return query(rs,mid+1,r,lim);
    }
    void build(int &now,int l,int r)
    {
        mi[now=++tot]=0;
        if(l==r) return;
        int mid=l+r>>1;
        build(ls,l,mid),build(rs,mid+1,r);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        memset(mi,0x3f,sizeof mi);
        build(root[0],1,++n);
        for(int a,i=1;i<n;i++)
        {
            scanf("%d",&a);
            if(a<n) rebuild(root[i-1],root[i],1,n,a+1,i);
            else root[i]=root[i-1];
        }
        for(int l,r,i=1;i<=m;i++)
        {
            scanf("%d%d",&l,&r);
            printf("%d
    ",query(root[r],1,n,l)-1);
        }
        return 0;
    }
    

    2019.1.28

  • 相关阅读:
    Elasticsearch安装中文分词器IK
    Docker安装ElasticSearch
    Docker安装
    Docker安装EOS
    Docker更改容器端口映射
    BoltDB 一个简单的纯 Go key/value 存储
    go语言 robfig/cron包 实现定时 调用
    GitHub 添加 SSH keys
    Android 端外推送到底有多烦?
    Nats的消息通信模型
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10331887.html
Copyright © 2011-2022 走看看