#include #ifdef LOCAL #include #else #define debug(...) void(0) #endif template struct IntervalManager { struct node { T l, r; S x; node(T l, T r, S x) : l(l), r(r), x(x) {} constexpr bool operator<(const node& rhs) const { return l != rhs.l ? l < rhs.l : r < rhs.r; } }; const S id = S(); std::set s; IntervalManager() {} IntervalManager(const std::vector& v) { std::vector tmp; for (size_t l = 0; l < v.size();) { size_t r = l; while (r < v.size() and v[l] == v[r]) r++; tmp.emplace_back(l, r, v[l]); l = r; } s = std::set(tmp.begin(), tmp.end()); } typename std::set::iterator getItr(const T& x) const { auto itr = s.upper_bound(node(x, std::numeric_limits::max(), id)); if (itr == s.begin()) return s.end(); itr = prev(itr); return itr->l <= x and x < itr->r ? itr : s.end(); } node getSeg(const T& x) const { auto itr = getItr(x); return itr != s.end() ? *itr : node(x, x + 1, id); } S get(const T& x) const { auto seg = getSeg(x); return seg.x; } S operator[](const T& x) const { return get(x); } template void apply(T l, T r, const S& x, const ADD& add, const DEL& del) { auto itr = s.lower_bound(node(l, std::numeric_limits::min(), id)); while (itr != s.end() and itr->l <= r) { if (itr->l == r) { if (itr->x == x) { del(itr->l, itr->r, itr->x); r = itr->r; itr = s.erase(itr); } break; } if (itr->r <= r) { del(itr->l, itr->r, itr->x); itr = s.erase(itr); } else { if (itr->x == x) { r = itr->r; del(itr->l, itr->r, itr->x); itr = s.erase(itr); } else { del(itr->l, r, itr->x); node tmp = *itr; itr = s.erase(itr); itr = s.emplace_hint(itr, r, tmp.r, tmp.x); } } } if (itr != s.begin()) { itr = prev(itr); if (itr->r == l) { if (itr->x == x) { del(itr->l, itr->r, itr->x); l = itr->l; itr = s.erase(itr); } } else if (l < itr->r) { if (itr->x == x) { del(itr->l, itr->r, itr->x); l = std::min(l, itr->l); r = std::max(r, itr->r); itr = s.erase(itr); } else { if (r < itr->r) { itr = s.emplace_hint(next(itr), r, itr->r, itr->x); itr = prev(itr); } del(l, std::min(r, itr->r), itr->x); node tmp = *itr; itr = s.erase(itr); itr = s.emplace_hint(itr, tmp.l, l, tmp.x); } } } add(l, r, x); s.emplace(l, r, x); } void apply(T l, T r, const S& x) { apply( l, r, x, [](T, T, S) {}, [](T, T, S) {}); } friend std::ostream& operator<<(std::ostream& os, const IntervalManager& im) { for (const auto& e : im) os << "([" << e.l << ", " << e.r << "): " << e.x << ") "; os << "\n"; return os; } }; using namespace std; typedef long long ll; #define all(x) begin(x), end(x) constexpr int INF = (1 << 30) - 1; constexpr long long IINF = (1LL << 60) - 1; constexpr int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1}; template istream& operator>>(istream& is, vector& v) { for (auto& x : v) is >> x; return is; } template ostream& operator<<(ostream& os, const vector& v) { auto sep = ""; for (const auto& x : v) os << exchange(sep, " ") << x; return os; } template bool chmin(T& x, U&& y) { return y < x and (x = forward(y), true); } template bool chmax(T& x, U&& y) { return x < y and (x = forward(y), true); } template void mkuni(vector& v) { sort(begin(v), end(v)); v.erase(unique(begin(v), end(v)), end(v)); } template int lwb(const vector& v, const T& x) { return lower_bound(begin(v), end(v), x) - begin(v); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, Q; cin >> N >> Q; IntervalManager IM; auto add = [&](int l, int r, int x) {}; auto del = [&](int l, int r, int x) {}; for (; Q--;) { int type; cin >> type; if (type == 1) { int L, R; cin >> L >> R; IM.apply(L, R, 1, add, del); } else if (type == 2) { int L, R; cin >> L >> R; IM.apply(L, R, 0, add, del); } else if (type == 3) { int u, v; cin >> u >> v; if (u > v) swap(u, v); if (u == v) { cout << 1 << '\n'; continue; } auto seg = IM.getSeg(u); cout << (seg.x == 1 and seg.r > v - 1) << '\n'; } else { int v; cin >> v; auto seg = IM.getSeg(v); debug(v, seg.l, seg.r); int ans = (seg.x == 0 ? 1 : seg.r - seg.l + 1); auto nseg = IM.getSeg(v - 1); if (seg.l != nseg.l and seg.r != nseg.r and nseg.x == 1) ans += nseg.r - nseg.l; cout << ans << '\n'; } } return 0; }