bzoj 3339: Rmq Problem

Description

Input

Output

Sample Input

7 5
0 2 1 0 1 3 2
1 3
2 3
1 4
3 6
2 7

Sample Output

3
0
3
2
4

HINT


又是第一眼看出了第一步然后不想去想了。。

我们先暴力弄出以1为开头到位置x的mex[x],可以体会到mex[]是单调的。

然后就可以乱搞了。

对于询问左端点排序,然后当左端点=当前mex左端点的时候直接输出

如果不等于,那么我们记录当前数下一个出现位置next[i]

那么可以把i+1到next[i]-1都更新一遍,因为mex是单调的,所以反过来更新,从next[i]-1到i+1,一旦不能更新就break

这样就可以得出所有的答案了

#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];
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 main()
{
	 //freopen("mex.in","r",stdin);
	 //freopen("mex.out","w",stdout);
     int q;
     scanf("%d%d",&n,&q);
     int i,j;
     for(i=1;i<=n;i++)
          scanf("%d",&a[i]);
     int now=0;
     for(i=1;i<=n;i++)
     {
     	  v[a[i]]=1;
          while(v[now]!=0)
               now++;
          mex[i]=now;
     }
     for(i=1;i<=n;i++)
     {
          next[last[a[i]]]=i;
          next[i]=n+1;
          last[a[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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值