#include <bits/stdc++.h>
using namespace std;
const int NR = 2e5 + 10;
const int mod = 998244353;
void Min(int& x, int y) { x = min(x, y); }
void Max(int& x, int y) { x = max(x, y); }
int read() {
  int x = 0, f = 1;
  char ch = getchar();
  while (ch > '9' || ch < '0') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch <= '9' && ch >= '0') {
    x = (x << 3) + (x << 1) + (ch ^ 48);
    ch = getchar();
  }
  return x * f;
}
int n, q;
struct Segment {
  int tr[NR << 2], lz1[NR << 2], lz2[NR << 2];
  void init() { memset(lz2, 1, sizeof(lz2)); }
  void update(int rt) { tr[rt] = (tr[(rt << 1)] + tr[(rt << 1 | 1)]) % mod; }
  void doit1(int rt, int v, int l, int r) {
    tr[rt] = (tr[rt] + 1ll * v * (r - l + 1) % mod) % mod;
    lz1[rt] = (lz1[rt] + v) % mod;
  }
  void doit2(int rt, int v) {
    tr[rt] = 1ll * tr[rt] * v % mod;
    lz1[rt] = 1ll * lz1[rt] * v % mod;
    lz2[rt] = 1ll * lz2[rt] * v % mod;
  }
  void push_down(int rt, int l, int r) {
    if (lz2[rt] != 1) {
      doit2((rt << 1), lz2[rt]), doit2((rt << 1 | 1), lz2[rt]);
      lz2[rt] = 1;
    }
    if (lz1[rt]) {
      int mid = (l + r) >> 1, x = lz1[rt];
      doit1((rt << 1), x, l, mid), doit1((rt << 1 | 1), x, mid + 1, r);
      lz1[rt] = 0;
    }
  }
  void change1(int rt, int l, int r, int L, int R, int v) {
    if (l == L && r == R) {
      doit1(rt, v, l, r);
      return;
    }
    int mid = (l + r) >> 1;
    push_down(rt, l, r);
    if (R <= mid)
      change1((rt << 1), l, mid, L, R, v);
    else if (L > mid)
      change1((rt << 1 | 1), mid + 1, r, L, R, v);
    else
      change1((rt << 1), l, mid, L, mid, v),
          change1((rt << 1 | 1), mid + 1, r, mid + 1, R, v);
    update(rt);
  }
  void change2(int rt, int l, int r, int L, int R, int v) {
    if (l == L && r == R) {
      doit2(rt, v);
      return;
    }
    int mid = (l + r) >> 1;
    push_down(rt, l, r);
    if (R <= mid)
      change2((rt << 1), l, mid, L, R, v);
    else if (L > mid)
      change2((rt << 1 | 1), mid + 1, r, L, R, v);
    else
      change2((rt << 1), l, mid, L, mid, v),
          change2((rt << 1 | 1), mid + 1, r, mid + 1, R, v);
    update(rt);
  }
  int query(int rt, int l, int r, int L, int R) {
    if (l == L && r == R) return tr[rt];
    int mid = (l + r) >> 1;
    push_down(rt, l, r);
    if (R <= mid)
      return query((rt << 1), l, mid, L, R);
    else if (L > mid)
      return query((rt << 1 | 1), mid + 1, r, L, R);
    else
      return (query((rt << 1), l, mid, L, mid) +
              query((rt << 1 | 1), mid + 1, r, mid + 1, R)) %
             mod;
  }
} T;
struct Mashiro {
  int l, r;
  bool operator<(const Mashiro& A) const {
    if (l == A.l) return r > A.r;
    return l < A.l;
  }
};
Mashiro mashiro(int l, int r) {
  Mashiro tmp;
  tmp.l = l, tmp.r = r;
  return tmp;
}
Mashiro merge(Mashiro A, Mashiro B) {
  return mashiro(min(A.l, B.l), max(A.r, B.r));
}
bool check(Mashiro A, Mashiro B) { return min(A.r, B.r) >= max(A.l, B.l); }
set<Mashiro> s[NR];
Mashiro cl[NR];
int tt = 0;
void solve() {
  int l = read(), r = read(), x = read();
  T.change1(1, 1, n, l, r, 1);
  if (s[x].begin() == s[x].end()) {
    s[x].insert(mashiro(l, r));
    return;
  }
  Mashiro tmp1 = mashiro(l, 0), tmp2 = mashiro(r, 0);
  set<Mashiro>::iterator it1 = s[x].lower_bound(tmp1);
  set<Mashiro>::iterator it2 = s[x].lower_bound(tmp2);
  if (it1 != s[x].begin()) it1--;
  if (it2 == s[x].begin()) {
    s[x].insert(mashiro(l, r));
    return;
  }
  Mashiro now = mashiro(l, r);
  if (!check(*it1, mashiro(l, r))) it1++;
  for (set<Mashiro>::iterator it = it1; it != it2; it++) {
    int L = (it->l), R = (it->r);
    L = max(L, l), R = min(r, R);
    T.change1(1, 1, n, L, R, -1);
    T.change2(1, 1, n, L, R, 2);
    now = merge(now, mashiro((it->l), (it->r)));
  }
  tt = 0;
  for (set<Mashiro>::iterator it = it1; it != it2; it++) cl[++tt] = (*it);
  for (int i = 1; i <= tt; i++) s[x].erase(cl[i]);
  s[x].insert(now);
}
void print() {
  int l = read(), r = read();
  printf("%d\n", T.query(1, 1, n, l, r));
}
int main() {
  n = read(), q = read();
  T.init();
  for (int i = 1; i <= q; i++) {
    int op = read();
    if (op == 1)
      solve();
    else
      print();
  }
  return 0;
}
