[清华集训]Rmq Problem / mex

题目链接

我们离线处理这些询问

在右端点所在的位置用vectorpush_back询问

维护每个数值最后出现的位置p[x]

从左往右扫,边走边回答询问

对于每个询问我们回答第一个p[x]<lx

这个可以用分块来维护

时间复杂度\(\Theta(n \sqrt{n})\)

#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
#include"vector"
#include"cmath"
using namespace std;

const int MAXN=2e5+5;

int n,m,siz;
int v[MAXN],id[MAXN],l[MAXN],r[MAXN],p[MAXN],mi[MAXN],ans[MAXN];
struct rpg{int l,id;};
vector<rpg> vec[MAXN];

void ins(int x,int v)
{
	if(x>=n) return;
	p[x]=v;mi[id[x]]=n;
	for(int i=l[x];i<=r[x];++i) mi[id[x]]=min(mi[id[x]],p[i]);
	return;
}

int query(int v)
{
	for(int i=0;i<n;i=r[i]+1){
		if(mi[id[i]]<v){
			for(int j=i;j<=r[i];++j){
				if(p[j]<v) return j;
			}
		}
	}return n;
}

int main()
{
	scanf("%d%d",&n,&m);siz=sqrt(n);
	for(int i=0;i<n;++i) id[i]=i/siz+1,l[i]=(id[i]-1)*siz,r[i]=min(id[i]*siz-1,n-1);
	for(int i=1;i<=n;++i) scanf("%d",&v[i]);
	for(int i=1;i<=m;++i){int l,r;scanf("%d%d",&l,&r);vec[r].push_back((rpg){l,i});}
	for(int i=1;i<=n;++i){
		ins(v[i],i);
		for(int j=0;j<vec[i].size();++j){
			ans[vec[i][j].id]=query(vec[i][j].l);
		}
	}for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
	return 0;
}
posted @ 2018-12-11 16:56  A·H  阅读(92)  评论(0编辑  收藏  举报