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
2 1 0 2 1
3 3
2 3
2 4
1 2
3 5
Sample Output
1
2
3
0
3
2
3
0
3
HINT
数据规模和约定
对于100%的数据:
1<=n,m<=200000
0<=ai<=109
1<=l<=r<=n
对于30%的数据:
1<=n,m<=1000
和3339一样
------------以下摘自3339------------
我们先暴力弄出以1为开头到位置x的mex[x],可以体会到mex[]是单调的。
然后就可以乱搞了。
对于询问左端点排序,然后当左端点=当前mex左端点的时候直接输出
如果不等于,那么我们记录当前数下一个出现位置next[i]
那么可以把i+1到next[i]-1都更新一遍,因为mex是单调的,所以反过来更新,从next[i]-1到i+1,一旦不能更新就break
这样就可以得出所有的答案了
--------------------------------------------然后这题只是多个离散化操作。给mex赋初值要稍微处理一下就好
#include<cstdio>
#include<algorithm>
using namespace std;
int a[200001],v[200001],last[200001],mex[200001],next[200001];
int ans[200001];
int n;
struct getask
{
int l,r;
int t;
}ask[200001];
struct num
{
int x,t;
}b[200001];
inline bool cmp(num x,num y)
{
if(x.x<y.x)
return true;
return false;
}
inline bool cmp1(getask x,getask y)
{
if(x.l<y.l)
return true;
return false;
}
inline bool cmp2(getask x,getask y)
{
if(x.t<y.t)
return true;
return false;
}
inline void change(int x)
{
int i;
int ed=next[x];
if(ed==0)
ed=n+1;
mex[x]=0;
for(i=ed-1;i>x;i--) //这里倒着更新太神。。
{
if(mex[i]>a[x])
mex[i]=a[x];
else
break;
}
}
int f[200001];
int fx[200001];
int main()
{
int q;
scanf("%d%d",&n,&q);
int i,j;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i].x=a[i];
b[i].t=i;
}
sort(b+1,b+1+n,cmp);
int tot=1;
f[tot]=0;
fx[0]=tot;
for(i=1;i<=n;i++)
{
if(b[i].x!=f[tot])
{
tot++;
f[tot]=b[i].x;
}
fx[b[i].t]=tot;
}
int now=1;
for(i=1;i<=n;i++)
{
int d;
v[fx[i]]=1;
while(v[now]!=0&&f[now+1]==f[now]+1)
now++;
if(v[now]!=0&&f[now+1]!=f[now]+1)
d=f[now]+1;
else
d=f[now];
mex[i]=d;
}
for(i=1;i<=n;i++)
{
next[last[fx[i]]]=i;
next[i]=n+1;
last[fx[i]]=i;
}
for(i=1;i<=q;i++)
{
scanf("%d%d",&ask[i].l,&ask[i].r);
ask[i].t=i;
}
sort(ask+1,ask+1+q,cmp1);
int la=1;
for(i=1;i<=q;i++)
{
if(ask[i].l==la)
ans[ask[i].t]=mex[ask[i].r];
else
{
for(j=la;j<ask[i].l;j++)
change(j);
ans[ask[i].t]=mex[ask[i].r];
}
la=ask[i].l;
}
for(i=1;i<=q;i++)
printf("%d\n",ans[i]);
return 0;
}