jzoj5710

版权声明:本博客為本人嘔心瀝血之作,未經允許禁止轉載! https://blog.csdn.net/qq_39529862/article/details/84402316

對於每個詢問,我們先考慮插入1~r中每個數的答案,這樣子就不用考慮後面數對現在的影響
那麼我們可以在權值線段樹的每一個位置存儲每一個值最後一次結束的位置
問題變成了,如何判斷區間連續?
我們可以對線段樹對應區間所有節點權值取最小值,我們發現如果有一個值<l,那麼有一個數不在區間內出現,區間就不連續,否則區間就連續

#include<bits/stdc++.h>
using namespace std;
#define N 200010
int n,m,a[N],lc[N<<5],rc[N<<5],rt[N],sz[N<<5],ct,la,t;
void ins(int &o,int p,int l,int r,int x,int y){
	if(!o)o=++ct;
	if(l==r){
		sz[o]=y;
		return;
	}
	int mid=(l+r)/2;
	if(x<=mid){
		rc[o]=rc[p];
		ins(lc[o],lc[p],l,mid,x,y);
	}
	else{
		lc[o]=lc[p];
		ins(rc[o],rc[p],mid+1,r,x,y);
	}
	sz[o]=min(sz[lc[o]],sz[rc[o]]);
}
int q(int o,int p,int l,int r,int x){
	if(l==r)return l;
	int mid=(l+r)/2;
	if(sz[lc[o]]>=x)return q(rc[o],rc[p],mid+1,r,x);
	return q(lc[o],lc[p],l,mid,x);
}
int main(){
	freopen("mex.in","r",stdin);
	freopen("mex.out","w",stdout); 
	scanf("%d%d%d",&n,&m,&t);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		ins(rt[i],rt[i-1],0,1e9+5,a[i],i);
	}
	while(m--){
		int l,r;
		scanf("%d%d",&l,&r);
		if(t)l^=la,r^=la;
		la=q(rt[r],rt[l-1],0,1e9+5,l);
		printf("%d\n",la);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_39529862/article/details/84402316