Rmq Problem / mex

link

莫队吸氧水过去的, \(O(N\sqrt N\log N)\) 吸氧能过二十万,感谢你谷的评测机大大。

没什么,用num数组和树状数组维护一个区间信息,树状数组为值域,有该数值为1,否则为0,查找时二分即可,因为当一个区间并不是所有数都在时查出来的区间和会不等于区间长度。要注意的是树状数组下标不能是0,所以所有数要加一处理。

#include<bits/stdc++.h>
//#define zczc
const int N=200010;
using namespace std;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}

int m,n,c[N],size;

struct node{
	int id,l,r;
}a[N];
inline bool cmp(node s1,node s2){
	if(s1.l/size==s2.l/size)return s1.r<s2.r;
	else return s1.l/size<s2.l/size;
}

int num[N];
#define lowbit (wh&-wh)
int t[N];
inline void change(int wh,int val){
	for(;wh<N;wh+=lowbit)t[wh]+=val;
}
inline int work(int wh){
	int an=0;
	for(;wh;wh-=lowbit)an+=t[wh];
	return an;
}
#undef lowbit

inline void add(int wh){
	if(num[wh]==0)change(wh,1);
	num[wh]++;
}
inline void del(int wh){
	num[wh]--;
	if(num[wh]==0)change(wh,-1);
}
inline int ans(){
	int l=1,r=N-1,mid;
	while(l<r){
		mid=l+r>>1;
		if(work(mid)==mid)l=mid+1;
		else r=mid;
	}
	return l-1;
}

int an[N];

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(n);
	for(int i=1;i<=m;i++){
		read(c[i]);c[i]++;
	}
	for(int i=1;i<=n;i++){
		a[i].id=i;
		read(a[i].l);read(a[i].r);
	}
	size=ceil(sqrt(m));
	sort(a+1,a+n+1,cmp);
	int l=1,r=0;
	for(int i=1;i<=n;i++){
		while(r<a[i].r)add(c[++r]);
		while(l>a[i].l)add(c[--l]);
		while(r>a[i].r)del(c[r--]);
		while(l<a[i].l)del(c[l++]);
		an[a[i].id]=ans();
	}
	for(int i=1;i<=n;i++)printf("%d\n",an[i]);
	
	return 0;
}
posted @ 2022-06-23 15:46  Feyn618  阅读(5)  评论(0编辑  收藏  举报