区间 mex 在平面上的矩形个数 。

从 到 ,set 维护 的连续段,单调递减。删去 即 对 取 min,即区间推平。

极小 mex 区间 个

只考虑 的极小 mex 区间。设 是,则 。若存在 且 也是,, 中有 ,可以删去 ,矛盾。

从小到大维护出 的极小 mex 区间。对于一个 ,找到 ,拓展为 和 作为对应的 mex 的候选区间。对于 的候选区间,删掉不优的即可。

主席树维护在线询问。

在求出最小 mex 区间后,可以再类似区间推平得到极大 mex 区间。

这样等价于求出矩形 后的 和 ,点数更小些。

code

int n,a[maxn];
struct node{
	int l,r,v,t;
	bool operator<(const node&tmp)const{return r<tmp.l;}
};
set<node> s;
bool vis[maxn];
int pos[maxn],pre[maxn];
vector<tuple<int,int,int,int,int>> b;
void work(){
	n=read();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=n,mex=1;i;i--){
		vis[a[i]]=1;while(vis[mex])mex++;
		s.insert({i,i,mex,n});
	}
	for(int i=1;i<=n;i++)pre[i]=pos[a[i]],pos[a[i]]=i;
	for(int i=n;i;i--){
		{
		auto it=s.find({i,i,0,0});
		auto[l,r,v,t]=*it;s.erase(it);
		if(l<i)s.insert({l,i-1,v,t});
		b.pb({v,i,i,i,t});
		}
		if(pre[i]+1==i)continue;
		{
			auto it=s.find({pre[i]+1,pre[i]+1,0,0});
			auto[l,r,v,t]=*it;
			if(l<=pre[i]){
				s.erase(it);
				s.insert({l,pre[i],v,t});
				s.insert({pre[i]+1,r,v,t});
			}
		}
		auto it=s.find({pre[i]+1,pre[i]+1,0,0});
		int p=pre[i];
		while(it!=s.end()&&(*it).v>a[i]){
			auto[l,r,v,t]=(*it);it=s.erase(it);
			b.pb({v,l,r,i,t});p=r;
		}
		if(pre[i]+1<=p)s.insert({pre[i]+1,p,a[i],i-1});
	}
	for(auto[v,l1,r1,l2,r2]:b){
        
	}
}

P13780