题意:现在有无穷多个位置(从 \(1\) 开始),一开始都是 \(0\),每次用 \(1/0\) 覆盖一个区间或翻转一个区间的 \(0/1\)。现在给出操作,求每次操作结束后第一个 \(0\) 的位置。

我们发现值域过大,不方便用数据结构维护,则考虑离散化。注意为了给可能存在的区间之间的空隙留下位置,例如 \([1,2]\)\([4,5]\),离散化之后变成 \([1,2][3,4]\)\(3\) 的存在失去了。则将 \(l\pm 1\)\(r\pm 1\) 一起离散化进去,但是注意如果 \(r-1\)\(l-1\)\(0\),不能加入。

然后考虑用线段树维护。我们在线段树上维护 \(sum,len,tg\),分别表示当前区间的 \(1\) 的总和、当前区间的总长度、当前区间面临的操作种类。

操作的过程,就是给区间打标记。

考虑如何打上或下传标记。

假设当前节点的标记种类是 \(tg\),新加入 \(d\),如果 \(tg=0\),直接用 \(d\) 覆盖。如果 \(d=1\)\(2\),也直接用 \(d\) 覆盖。如果 \(d\)\(3\),更改为 \(3-d\)。这样,原来的 \(1\)\(2\) 交换,原来是 \(3\) 则相当于没做。

然后考虑处理标记。若 \(tg=1\),令 \(sum=len\)。若 \(tg=2\),令 \(sum=0\)。若 \(tg=3\),令 \(sum=len-sum\)

最后考虑如何查询,我们从根节点开始递归,先递归左节点,如果左边满了(\(len=sum\)),就去右边,直到找到答案。因为我们离散化的时候离散化了 \(r_{max}+1\),所以一定会找到答案的。

还有一个问题,就是我们查询之后要上传答案。如果我们在左子树找到答案就返回,是不能正确得到答案的。正确的做法是即使左子树有答案了,也在右儿子 \(push\) 一下 \(tg\),从而正确的合并答案。

int n,t[100005];
ll l[100005],r[100005],v[600005],m;
struct node{
	int l,r,sum,tg,len;
}sg[2400005];
inline void init(int i,int l,int r){
	sg[i].l=l,sg[i].r=r,sg[i].tg=0,sg[i].sum=0,sg[i].len=(sg[i].r-sg[i].l+1);
	if(l==r)return;
	init(i<<1,l,l+r>>1);
	init(i<<1|1,(l+r>>1)+1,r);
}
inline void addtg(int i,int d){
	if(!sg[i].tg||d<=2)sg[i].tg=d;
	else sg[i].tg=3-sg[i].tg;
}
inline void psh(int i){
	if(!sg[i].tg)return;
	if(sg[i].tg==1)sg[i].sum=sg[i].len;
	else if(sg[i].tg==2)sg[i].sum=0;
	else sg[i].sum=sg[i].len-sg[i].sum;
	if(sg[i].l!=sg[i].r){
		addtg(i<<1,sg[i].tg);
		addtg(i<<1|1,sg[i].tg);
	}sg[i].tg=0;
}
inline void add(int i,int d,int l,int r){
	psh(i);
	if(sg[i].l>r||sg[i].r<l)return;
	if(sg[i].l>=l&&sg[i].r<=r){
		addtg(i,d);
		psh(i);
		return;
	}
	add(i<<1,d,l,r);
	add(i<<1|1,d,l,r);
	sg[i].sum=sg[i<<1].sum+sg[i<<1|1].sum;
}
inline int qry(int i,bool p){
	psh(i);
	if(sg[i].sum==sg[i].len||p)return -1;
	if(sg[i].l==sg[i].r)return sg[i].l;
	int res=qry(i<<1,0);
	if(res==-1)res=qry(i<<1|1,0);
	else qry(i<<1|1,1);
	sg[i].sum=sg[i<<1].sum+sg[i<<1|1].sum;
	return res;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n;
	v[++m]=1;
	rp(i,n){
		cin>>t[i]>>l[i]>>r[i];
		if(l[i]!=1)v[++m]=l[i]-1;
		v[++m]=l[i],v[++m]=l[i]+1;
		v[++m]=r[i],v[++m]=r[i]+1;
		if(r[i]!=1)v[++m]=r[i]-1;
	}
	sort(v+1,v+1+m);
	m=unique(v+1,v+1+m)-v-1;
	init(1,1,m);
	rp(i,n){
		l[i]=lower_bound(v+1,v+1+m,l[i])-v;
		r[i]=lower_bound(v+1,v+1+m,r[i])-v;
	}
	rp(i,n){
		add(1,t[i],l[i],r[i]);
		cout<<v[qry(1,0)]<<'\n';
	}
	return 0;
}
//Crayan_r