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

    题目描述

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

    输入输出格式

    输入格式:

    第一行n,m。

    第二行为n个数。

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

    输出格式:

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

    输入输出样例

    输入样例#1: 
    5 5
    2 1 0 2 1
    3 3
    2 3
    2 4
    1 2
    3 5
    输出样例#1: 
    1
    2
    3
    0
    3

    说明

    对于30%的数据:1<=n,m<=1000

    对于100%的数据:1<=n,m<=200000,0<=ai<=10^9,1<=l<=r<=n

    Solution:

      本题又是区间上的操作,而且操作还这么诡异,于是果断往莫队上想。

      很容易想到维护一段区间$[l,r]$的最小值$ansmin$,用一个数组统计每个数字出现的次数,然后每次对$ansmin$的值进行修改,具体就是当某数字增加时暴力求出当前最小的没有出现的数,当某数字减少时若减小到$0$则与$ansmin$取最小值就行了。

      但是有个很大的问题,本题的数据$a[i] leq 10^9$这就是真的骚,果断切掉这算法,看波题解,发现别人竟然用这方法$AC$了,真的神奇。于是忽略数据范围来乱写,果真$AC$了。

      最蛇皮的是,我想试一下模数取$520$能不能过,结果$10$分,神奇的是我换回原来代码后,死活$AC$不了,什么$RE,TLE,WA$都出来了,简直神奇。

      后面想到一个问题就是答案肯定最大为$200001$以内,因为一共就$200000$个数,每个被覆盖,最大显然是$200001$。

      于是就可以直接将比$200000$大的数去掉就OK了。整个复杂度是玄学的,嘿嘿!(巨说正解的mex求法就是分块,可以去学学)

      看了一下别人的算法,都是什么高超的数据结构(挖个坑下次学学用权值线段树+离线或者持久化写写这题),但还是贴一下莫队的代码吧,本题真蛇皮啊~~手动滑稽~~。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    using namespace std;
    const int N=200005;
    int n,m,ansmin,pos[N],a[N],ans[N],s[N];
    struct data{
        int l,r,id;
    }t[N];
    il int gi()
    {
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
        return f?-a:a;
    }
    il bool cmp(data a,data b){return pos[a.l]==pos[b.l]?a.r<b.r:a.l<b.l;}
    il void change(int k,int u)
    {
        if(a[k]>200000)return;
        if(u==1){
            s[a[k]]++;int i=ansmin;while(s[i])i++;ansmin=i;
        }
        else {
            s[a[k]]--;if(!s[a[k]])ansmin=min(ansmin,a[k]);
        }
    }
    int main()
    {
        n=gi(),m=gi();
        int ss=int(sqrt(n));
        for(int i=1;i<=n;i++)a[i]=gi(),pos[i]=(i-1)/ss+1;
        for(int i=1;i<=m;i++)t[i].l=gi(),t[i].r=gi(),t[i].id=i;
        sort(t+1,t+m+1,cmp);
        for(int i=1,l=1,r=0;i<=m;i++){
            while(r<t[i].r)change(r+1,1),r++;
            while(r>t[i].r)change(r,-1),r--;
            while(l<t[i].l)change(l,-1),l++;
            while(l>t[i].l)change(l-1,1),l--;
            if(t[i].l==t[i].r){ans[t[i].id]=0;continue;}
            ans[t[i].id]=ansmin;
        }
        for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
        return 0;
    }

  • 相关阅读:
    将Moba的输出导出为文件
    MyBatis入参为0时失效问题
    (笔记)交大电院MEM提前面试优秀经验分享【附面试流程及规则】
    (笔记)GPIO基本原理与寄存器配置(STM32篇)
    (笔记)高速电路板完美走线的诀窍
    使用 python 收集 kubernetes events 并写入 elasticsearch
    java使用io.kubernetes.client-java调用k8s api创建pod/service/ingress示例
    中英文逗号空格分隔符正则式
    SpringCloud学习一-搭建netflix-eureka微服务集群
    Spring 中经典的 9 种设计模式,打死也要记住啊!
  • 原文地址:https://www.cnblogs.com/five20/p/8798672.html
Copyright © 2011-2022 走看看