#include <bits/stdc++.h>
#pragma GCC optimize("O2")
using namespace std;
const int MXN = 2e5 + 10;
const int MXS = MXN * 4;
const int INF = 1e9;
const int Mod = 998244353;
int n, q, num;
int Seg[MXS], MUL[MXS], ADD[MXS];
set<pair<pair<int, int>, int> > st[MXN];
void Shift(int id, int s, int e) {
  if (MUL[id] == 1 && ADD[id] == 0) return;
  Seg[id] =
      ((1ll * Seg[id] * MUL[id] % Mod) + (1ll * ADD[id] * (e - s + 1) % Mod)) %
      Mod;
  if ((e - s + 1) > 1) {
    ADD[(id * 2)] = ((1ll * ADD[(id * 2)] * MUL[id] % Mod) + ADD[id]) % Mod;
    ADD[(id * 2 + 1)] =
        ((1ll * ADD[(id * 2 + 1)] * MUL[id] % Mod) + ADD[id]) % Mod;
    MUL[(id * 2)] = 1ll * MUL[(id * 2)] * MUL[id] % Mod;
    MUL[(id * 2 + 1)] = 1ll * MUL[(id * 2 + 1)] * MUL[id] % Mod;
  }
  ADD[id] = 0, MUL[id] = 1;
}
void Upd(int l, int r, int add, int mul, int id = 1, int s = 1, int e = n) {
  Shift(id, s, e);
  if (e < l || s > r) return;
  if (l <= s && e <= r) {
    ADD[id] = add, MUL[id] = mul;
    Shift(id, s, e);
    return;
  }
  Upd(l, r, add, mul, (id * 2), s, ((s + e) / 2)),
      Upd(l, r, add, mul, (id * 2 + 1), ((s + e) / 2 + 1), e);
  Seg[id] = (Seg[(id * 2)] + Seg[(id * 2 + 1)]) % Mod;
}
int Get(int l, int r, int id = 1, int s = 1, int e = n) {
  Shift(id, s, e);
  if (e < l || s > r) return 0;
  if (l <= s && e <= r) return Seg[id];
  return (Get(l, r, (id * 2), s, ((s + e) / 2)) +
          Get(l, r, (id * 2 + 1), ((s + e) / 2 + 1), e)) %
         Mod;
}
void Split(int tp, int p, bool f) {
  auto itr = st[tp].upper_bound({{p, INF}, 0});
  itr--;
  int l, r, sit = itr->second;
  tie(l, r) = itr->first;
  if (!f && l == p) return;
  if (f && r == p) return;
  st[tp].erase(itr);
  st[tp].insert({{l, p - 1 + f}, sit});
  st[tp].insert({{p + f, r}, sit});
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> q;
  for (int i = 0; i < MXS; i++) MUL[i] = 1;
  for (int i = 1; i <= n; i++) st[i].insert({{1, n}, 0});
  for (int i = 0; i < q; i++) {
    int t, l, r, x;
    cin >> t >> l >> r;
    if (t != 2) cin >> x;
    if (t == 2) {
      cout << Get(l, r) << '\n';
      continue;
    }
    Split(x, l, 0), Split(x, r, 1);
    auto itr = st[x].lower_bound({{l, l}, 0});
    while (itr != st[x].end() && itr->first.second <= r) {
      int nl, nr, ns = itr->second;
      tie(nl, nr) = itr->first;
      if (ns) Upd(nl, nr, 0, 2);
      if (!ns) Upd(nl, nr, 1, 1);
      st[x].erase(itr);
      itr = st[x].lower_bound({{nr + 1, nr + 1}, 0});
    }
    st[x].insert({{l, r}, 1});
  }
  return 0;
}
