题解 P4137 Rmq Problem / mex

莫队其实是可以过这题的数据范围的。

因为 \(mex < n\) ,所以修改时对于 \(a_{i} \ge n\) ,可将其特判掉。

故剩余的 \(a_{i}\) 都有 \(a_{i} < n\) ,此时可用桶记录每个数出现的次数。

莫队正常操作排序后,再对每次两个区间的不同部分暴力修改。

发现会超时。只要加一个小优化即可通过:

在排序的时候,判断对于第 \(i,j\) 个结构体 \(q_{i}\)\(q_{j}\) ,是否有

\(\frac{q_{i}.l}{\sqrt{n}} < \frac{q_{j}.l}{\sqrt{n}}\)

如果是就直接排序;否则判断是否有

\(q_{i}.r < q_{j}.r\)

如果是就直接排序;否则按

\(q_{i}.l < q_{j}.l\)

排序。

\(code\)

#include<cstdio>
#include<algorithm>
#include<cmath>
#define R register
using namespace std;
int n,m,sqn;
int a[200002],bel[200002],num[200002]={};
struct aaa
{
	int l,r,num,ans;
}q,qry[200002];
template<class T>void read(T &x)
{
	x=0;int f=0;char ch=getchar();
	while(ch<'0' || ch>'9')f|=(ch=='-'),ch=getchar();
	while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	x=f? -x:x;return ;
}
inline bool cmp(aaa a,aaa b)
{
	return (bel[a.l]==bel[b.l])? ((a.r==b.r)? (a.l<b.l):(a.r<b.r)):(bel[a.l]<bel[b.l]);
}
inline bool cmp1(aaa a,aaa b)
{
	return a.num<b.num;
}
int main()
{
	read(n),read(m),sqn=n/sqrt(m);
	for(R int i=1;i<=n;++i)read(a[i]),bel[i]=i/sqn;
	for(R int i=1;i<=m;++i)read(qry[i].l),read(qry[i].r),qry[i].num=i;
	int l=1,r=0,now_ans=0;sort(qry+1,qry+m+1,cmp);
	for(R int i=1;i<=m;++i)
	{
		q=qry[i];if(q.l>q.r){qry[i].ans=0;continue;}
		while(l>q.l){if(a[--l]<n)++num[a[l]];while(num[now_ans])++now_ans;}
		while(r<q.r){if(a[++r]<n)++num[a[r]];while(num[now_ans])++now_ans;}
		while(l<q.l){if(a[l]<n && !(--num[a[l]]) && a[l]<now_ans)now_ans=a[l];++l;}
		while(r>q.r){if(a[r]<n && !(--num[a[r]]) && a[r]<now_ans)now_ans=a[r];--r;}
		qry[i].ans=now_ans;
	}
	sort(qry+1,qry+m+1,cmp1);
	for(R int i=1;i<=m;++i)printf("%d\n",qry[i].ans);
	return 0;
}
posted @ 2021-03-13 11:46  18Michael  阅读(48)  评论(0编辑  收藏  举报