Rmq Problem / mex

题意

给定一个序列以及若干查询,每次查询求不被区间包含的最小正整数值。


思路

复杂度不正确的裸莫队也能过。

删除操作直接取最小值,添加操作暴力寻找最小值。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

	template<typename T>inline void read (T &x) {
		x=0;T f=1;char c=getchar();
		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
		x*=f;
	}

	template<typename T>inline void write (T x) {
		if (x<0) putchar('-'),x*=-1;
		if (x>=10) write(x/10);
		putchar(x%10+'0');
	}

}

using namespace StandardIO;

namespace Project {
	
	const int N=200200;
	
	int n,m,block;
	int a[N];
	struct ask {
		int l,r,id;
	} q[N];
	int cnt[N],ans[N],res;
	
	inline bool cmp (const ask x,const ask y) {
		return (x.l/block!=y.l/block)?(x.l/block<y.l/block):(((x.l/block)&1)?x.r<y.r:x.r>y.r);
	}
	inline void add (int x) {
		++cnt[a[x]];
		if (cnt[a[x]]==1&&res==a[x]) {
			int tmp=a[x];
			while (cnt[tmp]) ++tmp;
			res=tmp;
		}
	}
	inline void del (int x) {
		--cnt[a[x]];
		if (!cnt[a[x]]) res=min(res,a[x]);
	}

	inline void MAIN () {
		read(n),read(m),block=sqrt(n);
		for (register int i=1; i<=n; ++i) read(a[i]);
		for (register int i=1; i<=m; ++i) read(q[i].l),read(q[i].r),q[i].id=i;
		sort(q+1,q+m+1,cmp);
		int l=1,r=0;
		for (register int i=1; i<=m; ++i) {
			while (l>q[i].l) add(--l);
			while (r<q[i].r) add(++r);
			while (l<q[i].l) del(l++);
			while (r>q[i].r) del(r--);
			ans[q[i].id]=res;
		}
		for (register int i=1; i<=m; ++i) {
			write(ans[i]),puts("");
		}
	}
	
}

int main () {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	Project::MAIN();
}
原文地址:https://www.cnblogs.com/ilverene/p/11704156.html