题意:给定一个初始全为 0 0 0 的串,每次对于区间 [ l , r ] [l, r] [l,r],有三种操作:
1 - add:将区间置1
2 - remove:将区间置0
3 - invert:将区间 01 翻转
每次操作完输出 M E X MEX MEX
由于 1 ≤ l , r ≤ 1 0 18 1\leq l , r\leq10^{18} 1≤l,r≤1018, 考虑离散化,需要将 1 , l , r , r + 1 1,l,r,r+1 1,l,r,r+1离散,这些点都可能是答案
ll n, m, cnt;
//用 b数组来维护离散化后的结果
ll b[maxn * 3];
struct Node{
ll op, l, r;
}a[maxn];
struct node{
ll sum, l, r, lazy, lazy1;
//lazy = 0 或 1, 0表示不需要翻转,1表示需要翻转
//lazy1 = -1 或 0 或 1, -1表示子区间没有置 0或置 1操作, 0表示子区间有置 0, 1表示子区间有置 1操作
}tree[maxn * 12];
void push_up(ll p)
{
tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum;
}
void push_down(ll p)
{
if (tree[p].lazy1 == 1) //若有置 1操作,区间和为区间长度,若本身有翻转操作,会被置 1操作覆盖,所以lazy = 0
{
tree[p].lazy1 = -1;
tree[p << 1].sum = tree[p << 1].r - tree[p << 1].l + 1;
tree[p << 1].lazy = 0;
tree[p << 1].lazy1 = 1;
tree[p << 1 | 1].sum = tree[p << 1 | 1].r - tree[p << 1 | 1].l + 1;
tree[p << 1 | 1].lazy = 0;
tree[p << 1 | 1].lazy1 = 1;
}
else if (!tree[p].lazy1) //若有置 0操作,全部为 0,同理翻转操作会被覆盖
{
tree[p].lazy1 = -1;
tree[p << 1].sum = 0;
tree[p << 1].lazy1 = 0;
tree[p << 1].lazy = 0;
tree[p << 1 | 1].sum = 0;
tree[p << 1 | 1].lazy1 = 0;
tree[p << 1 | 1].lazy = 0;
}
else if (tree[p].lazy) //如果没有置 0或置 1操作,但有翻转操作
{
tree[p].lazy = 0;
//因为取反,原来是 0现在是1,原来是 1现在是 0,所以区间和等于长度 - 原区间和
tree[p << 1].sum = tree[p << 1].r - tree[p << 1].l + 1 - tree[p << 1].sum;
//若子区间有置 0或置 1操作, lazy1取反
if (tree[p << 1].lazy1 != -1)
tree[p << 1].lazy1 ^= 1;
//子区间没有置 0或置 1操作,子区间 lazy取反
else
tree[p << 1].lazy ^= 1;
tree[p << 1 | 1].sum = tree[p << 1 | 1].r - tree[p << 1 | 1].l + 1 - tree[p << 1 | 1].sum;
if (tree[p << 1 | 1].lazy1 != -1)
tree[p << 1 | 1].lazy1 ^= 1;
else
tree[p << 1 | 1].lazy ^= 1;
}
}
void add(ll ql, ll qr, ll p)
{
ll l = tree[p].l;
ll r = tree[p].r;
if (ql <= l && qr >= r)
{
tree[p].sum = r - l + 1;
tree[p].lazy = 0;
tree[p].lazy1 = 1;
return;
}
push_down(p);
ll mid = (l + r) >> 1;
if (ql <= mid)
add(ql, qr, p << 1);
if (qr > mid)
add(ql, qr, p << 1 | 1);
push_up(p);
}
void rem(ll ql, ll qr, ll p)
{
ll l = tree[p].l;
ll r = tree[p].r;
if (ql <= l && qr >= r)
{
tree[p].sum = 0;
tree[p].lazy = 0;
tree[p].lazy1 = 0;
return;
}
push_down(p);
ll mid = (l + r) >> 1;
if (ql <= mid)
rem(ql, qr, p << 1);
if (qr > mid)
rem(ql, qr, p << 1 | 1);
push_up(p);
}
void invert(ll ql, ll qr, ll p)
{
ll l = tree[p].l;
ll r = tree[p].r;
if (ql <= l && qr >= r)
{
tree[p].sum = r - l + 1 - tree[p].sum;
if (tree[p].lazy1 != -1)
tree[p].lazy1 ^= 1;
else
tree[p].lazy ^= 1;
return;
}
push_down(p);
ll mid = (l + r) >> 1;
if (ql <= mid)
invert(ql, qr, p << 1);
if (qr > mid)
invert(ql, qr, p << 1 | 1);
push_up(p);
}
ll query(ll p)
{
ll l = tree[p].l;
ll r = tree[p].r;
if (l == r)
return b[l];
push_down(p);
//若区间和小于区间长度,说明有未出现的点
if (tree[p << 1].sum < tree[p << 1].r - tree[p << 1].l + 1)
return query(p << 1);
return query(p << 1 | 1);
}
void build(ll l, ll r, ll p)
{
tree[p].l = l;
tree[p].r = r;
tree[p].sum = 0;
tree[p].lazy = 0;
tree[p].lazy1 = -1;
if (l == r)
return;
int mid = (l + r) >> 1;
build(l, mid, p << 1);
build(mid + 1, r, p << 1 | 1);
}
void solve()
{
cin >> n;
//离散化, 1, l, r, r + 1都需要被离散化
b[++cnt] = 1;
for (int i = 1; i <= n; i++)
{
cin >> a[i].op >> a[i].l >> a[i].r;
b[++cnt] = a[i].l;
b[++cnt] = a[i].r;
b[++cnt] = a[i].r + 1;
}
sort(b + 1, b + 1 + cnt);
ll len = unique(b + 1, b + 1 + cnt) - (b + 1);
build(1, len, 1);
for (int i = 1; i <= n; i++)
{
ll l = lower_bound(b + 1, b + 1 + len, a[i].l) - b;
ll r = lower_bound(b + 1, b + 1 + len, a[i].r) - b;
if (a[i].op == 1)
add(l, r, 1);
else if (a[i].op == 2)
rem(l, r, 1);
else
invert(l, r, 1);
cout << query(1) << endl;
}
}