题目描述
有一个长度为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;
}