Rmq Problem/mex BZOJ3339 BZOJ3585

分析:

一开始没看懂题...

后来想用二分答案却不会验证...

之后,想到用主席树来维护...

建一个权值线段树,维护出这个权值以前所有的点最晚在哪里出现...

之后,查一下是不是比查询区间的l断点大...如果小,往左查,如果大,往右查...

附上代码...

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cmath>
#include <cstring>
#include <cstdlib>
using namespace std;
#define N 200005
#define lson l,m,tr[rt].ls
#define rson m+1,r,tr[rt].rs
struct node
{
	int ls,rs,minn;
}tr[N*20];
int a[N],rot[N],n,Q,cnt;
void insert(int x,int l,int r,int &rt,int v,int c)
{
	if(!rt)rt=++cnt;
	if(l==r)
	{
		tr[rt].minn=c;
		return ;
	}
	int m=(l+r)>>1;
	if(m>=v)tr[rt].rs=tr[x].rs,insert(tr[x].ls,lson,v,c);
	else tr[rt].ls=tr[x].ls,insert(tr[x].rs,rson,v,c);
	tr[rt].minn=min(tr[tr[rt].ls].minn,tr[tr[rt].rs].minn);
}
int query(int l,int r,int rt,int k)
{
	if(l==r)return l;
	int m=(l+r)>>1;
	if(tr[tr[rt].ls].minn<k)return query(lson,k);
	else return query(rson,k);
}
int main()
{
	scanf("%d%d",&n,&Q);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		insert(rot[i-1],0,200000,rot[i],a[i],i);
	}
	while(Q--)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		printf("%d
",query(0,200000,rot[y],x));
	}
}

  

原文地址:https://www.cnblogs.com/Winniechen/p/8991634.html