$des$
一个无限长的 01 序列,初始全为 0,每次选择一个区间 [l,r] 进行操作,有三种操作:
1. l r 将 [l,r] 中所有元素变成 1。
2. l r 将 [l,r] 中所有元素变成 0。
3. l r 将 [l,r] 中所有元素异或上 1。
每次操作后询问最左边的 0 在哪个位置.
$sol$
线段树
将所有可能成为答案的点加入线段树的根节点维护
$code$
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cmath> #include <cstring> using namespace std; #define LL long long #define Rep(i, a, b) for(int i = a; i <= b; i ++) #define gc getchar() inline LL read() { LL x = 0; char c = gc; while(c < '0' || c > '9') c = gc; while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x; } const int N = 1e5 + 10, M = N * 6 * 2; struct Node { LL opt, l, r; } Ask[N]; LL A[M], js; int n; struct Node_ { int Cnt[2][M << 2], Size[M << 2], F[M << 2]; #define lson jd << 1 #define rson jd << 1 | 1 void Build_tree(int l, int r, int jd) { F[jd] = -1; Size[jd] = r - l + 1; Cnt[0][jd] = Size[jd]; if(l == r) return ; int mid = (l + r) >> 1; Build_tree(l, mid, lson), Build_tree(mid + 1, r, rson); } void Push_down(int jd) { int f = F[jd]; if(f == 1) { F[lson] = F[rson] = 1; Cnt[1][lson] = Size[lson], Cnt[1][rson] = Size[rson]; Cnt[0][lson] = 0, Cnt[0][rson] = 0; F[jd] = -1; } else if(f == 0) { F[lson] = F[rson] = 0; Cnt[0][lson] = Size[lson], Cnt[0][rson] = Size[rson]; Cnt[1][lson] = 0, Cnt[1][rson] = 0; F[jd] = -1; } else { if(F[lson] == 2) { swap(Cnt[1][lson], Cnt[0][lson]); F[lson] = -1; } else { if(F[lson] == -1) { F[lson] = 2; swap(Cnt[1][lson], Cnt[0][lson]); } else if(F[lson] == 0) { F[lson] = 1; Cnt[1][lson] = Size[lson], Cnt[0][lson] = 0; } else { F[lson] = 0; Cnt[0][lson] = Size[lson], Cnt[1][lson] = 0; } } if(F[rson] == 2) { swap(Cnt[1][rson], Cnt[0][rson]); F[rson] = -1; } else { if(F[rson] == -1) { F[rson] = 2; swap(Cnt[1][rson], Cnt[0][rson]); } else if(F[rson] == 0) { F[rson] = 1; Cnt[1][rson] = Size[rson], Cnt[0][rson] = 0; } else { F[rson] = 0; Cnt[0][rson] = Size[rson], Cnt[1][rson] = 0; } } F[jd] = -1; } } void Sec_G(int l, int r, int jd, int x, int y, int num){ if(x <= l && r <= y) { Cnt[num][jd] = Size[jd]; Cnt[num ^ 1][jd] = 0; F[jd] = num; // cout << Cnt[1][jd] << " " << Cnt[0][jd] << "\n"; return ; } if(F[jd] != -1) Push_down(jd); int mid = (l + r) >> 1; // cout << Cnt[0][lson] << "\n"; if(x <= mid) Sec_G(l, mid, lson, x, y, num); if(y > mid) Sec_G(mid + 1, r, rson, x, y, num); Cnt[1][jd] = Cnt[1][lson] + Cnt[1][rson]; Cnt[0][jd] = Cnt[0][lson] + Cnt[0][rson]; } int Ask(int l, int r, int jd) { if(l == r) { return l; } if(F[jd] != -1) Push_down(jd); int mid = (l + r) >> 1; // cout << Cnt[0][lson] << "\n"; if(Cnt[0][lson]) return Ask(l, mid, lson); else return Ask(mid + 1, r, rson); } void Seg_fz(int l, int r, int jd, int x, int y) { if(x <= l && r <= y) { if(F[jd] == -1) { swap(Cnt[1][jd], Cnt[0][jd]); F[jd] = 2; return ; } else if(F[jd] == 0) { F[jd] = 1; Cnt[1][jd] = Size[jd]; Cnt[0][jd] = 0; } else if(F[jd] == 1) { F[jd] = 0; Cnt[1][jd] = 0; Cnt[0][jd] = Size[jd]; } else { F[jd] = -1; swap(Cnt[1][jd], Cnt[0][jd]); } return ; } if(F[jd] != -1) Push_down(jd); int mid = (l + r) >> 1; // cout << Cnt[0][lson] << "\n"; if(x <= mid) Seg_fz(l, mid, lson, x, y); if(y > mid) Seg_fz(mid + 1, r, rson, x, y); Cnt[1][jd] = Cnt[1][lson] + Cnt[1][rson]; Cnt[0][jd] = Cnt[0][lson] + Cnt[0][rson]; } } Segtree; inline LL Getans() { int w = Segtree.Ask(1, js, 1); // if(A[w - 1] + 1 != A[w]) return A[w - 1] + 1; // else return A[w]; return A[w]; } int main() { freopen("a.in", "r", stdin); freopen("a.out", "w", stdout); n = read(); Rep(i, 1, n) { LL opt = read(), l = read(), r = read(); A[++ js] = l, A[++ js] = r; A[++ js] = max(1ll, l - 1), A[++ js] = r + 1; Ask[i] = (Node) { opt, l, r }; } A[++ js] = 1; sort(A + 1, A + js + 1); js = unique(A + 1, A + js + 1) - A - 1; Segtree.Build_tree(1, js, 1); // Rep(i, 1, 10) cout << Segtree.F[i] << " "; // return 0; Rep(i, 1, n) { LL opt = Ask[i].opt, l = Ask[i].l, r = Ask[i].r; int wl = lower_bound(A + 1, A + js + 1, l) - A; int wr = lower_bound(A + 1, A + js + 1, r) - A; if(opt == 1) { Segtree.Sec_G(1, js, 1, wl, wr, 1); cout << Getans() << "\n"; } else if(opt == 2) { Segtree.Sec_G(1, js, 1, wl, wr, 0); cout << Getans() << "\n"; } else { Segtree.Seg_fz(1, js, 1, wl, wr); cout << Getans() << "\n"; } } return 0; }