Jzoj3547 MEX

227 篇文章 3 订阅
134 篇文章 0 订阅

有一个长度为n的数组{a1,a2,...,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。

这是一个经典的主席树的题目,对于每个节点i开一颗线段树存储[1,i]区间内每个数最后出现的位置,那么查找的时候直接再树上类似平衡树找最小即可

#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 200010
#define M 1000000000
using namespace std;
struct tree{
	int l,r,v;
} s[N*50];
int rt[N],n,m,cnt=0;
void insert(int l,int r,int r1,int& r2,int k,int id){
	if(!r2) r2=++cnt;
	if(l==r){ s[r2].v=id; return; }
	int m=l+r>>1;
	if(k<=m){ s[r2].r=s[r1].r; insert(l,m,s[r1].l,s[r2].l,k,id); }
	else { s[r2].l=s[r1].l; insert(m+1,r,s[r1].r,s[r2].r,k,id); }
	s[r2].v=min(s[s[r2].l].v,s[s[r2].r].v);
}
int query(int l,int r,int r1,int k){
	if(s[r1].v>=k) return M;
	if(l==r) return l;
	int m=l+r>>1;
	if(s[s[r1].l].v<k) return query(l,m,s[r1].l,k);
	return query(m+1,r,s[r1].r,k);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int x,i=1;i<=n;++i){
		scanf("%d",&x);
		insert(0,M,rt[i-1],rt[i],x,i);
	}
	for(int l,r;m--;){
		scanf("%d%d",&l,&r);
		printf("%d\n",query(0,M,rt[r],l));
	}
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值