LGOJ P4137 Rmq Problem / mex

####题目描述 有一个长度为n的数组${a_1,a_2,…,a_n}$。$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







#####MO模板照常打;

难点在$add$函数上。给我的教训是,变量名最好要有实际意义,不要盲目追求短小,否则巨难debug。

↓拿到了一个新的元素,检查是否是刚刚加入的。如果是,并且这个数是原来区间的$mex$,那么就暴力更新新的 $mex$即可。

inline void add(int pos)
{
    cnt[a[pos]]++;
    if(cnt[a[pos]]==1&&now==a[pos])
    {
        int tmp=a[pos];
        while(cnt[tmp]!=0)tmp++;
        now=tmp;
        return;
    }
}





#####灵异事件

开$o2$会WA两个点,我猜是$cmp$函数的锅:

return (belong[i.l] ^ belong[j.l]) ? (belong[i.l]<belong[j.l]):((belong[i.l]&1)? i.r<j.r:i.r>j.r);

这个玄学优化可能是厌氧的




code:

#include<bits/stdc++.h>
using namespace std;
const int M=200010;
int n,m,a[M],belong[M],size,bnum,ans[M],now;
int L=1,R=0,ql,qr;
//map<int,int> cnt;
int cnt[M];

inline int read()
{
    char c=getchar();int x=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        x=x*10+c-'0';
    return x;
}

void pr(int x)
{
    if(x/10) pr(x/10);
    putchar(x%10+'0');
}
struct query
{
    int l,r,id;
}q[M];

bool cmp(query i,query j)
{
    return (belong[i.l] ^ belong[j.l]) ? (belong[i.l]<belong[j.l]):((belong[i.l]&1)? i.r<j.r:i.r>j.r);
    //return (belong[i.l]==belong[j.l]) ? i.r<j.r : i.l<j.l;
}

inline void add(int pos)
{
    //if((!(1+cnt[a[x]]))&&a[x]<now)now=a[x];
    cnt[a[pos]]++;
    if(cnt[a[pos]]==1&&now==a[pos])
    {
//        cnt[a[x]]++;
        int tmp=a[pos];
        while(cnt[tmp]!=0)tmp++;
        now=tmp;
        return;
        // while(++tmp)
        // {
        //     if(cnt[tmp]==0)
        //     {
        //         now=tmp;
        //         return ;
        //     }
        // }
    }
}


inline void del(int pos)
{
    if((!(--cnt[a[pos]]))&&a[pos]<now)now=a[pos];
}

int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=m;i++)
    {
        q[i].id=i;
        q[i].l=read();
        q[i].r=read();
    }
    size=sqrt(n);
    bnum= ceil((double)n/size);
    for(int i=1;i<=bnum;i++)
        for(int j=(i-1)*size+1;j<=i*size;j++)
            belong[j]=i;
   // for(int i=1;i<=n;i++)cout<<belong[i]<<' ';        
    sort(q+1,q+m+1,cmp);

    for(int i=1;i<=m;i++)
    {
        ql=q[i].l;qr=q[i].r;
        while(L<ql) del(L++);
        while(L>ql) add(--L);
        while(R>qr) del(R--);
        while(R<qr) add(++R);
        ans[q[i].id]=now; 
    }
    for(int i=1;i<=m;i++)pr(ans[i]),putchar('\n');

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/kion/p/11817121.html