#include <bits/stdc++.h>
#pragma optimization_level 3
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
using namespace std;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
int mod = 998244353;
struct DO {
  DO *l = 0, *r = 0;
  long long s = 0, A = 1, B = 0, sz = 0;
  DO() {}
  DO(int a) {
    sz = 1;
    s = a;
  }
  DO(DO *a, DO *b) {
    l = a, r = b;
    sz = l->sz + r->sz;
    s = (l->s + r->s) % mod;
  }
};
DO *build(int l, int r) {
  if (l == r) return new DO(0);
  int md = (l + r) / 2;
  return new DO(build(l, md), build(md + 1, r));
}
void UPD(DO *d) {
  assert(d->l);
  d->s = (d->l->s + d->r->s) % mod;
}
void push(DO *d) {
  if (!d->l) {
    d->A = 1;
    d->B = 0;
    return;
  }
  long long A2 = d->A, B2 = d->B;
  d->l->s = (d->l->s * A2 + d->l->sz * B2) % mod;
  d->r->s = (d->r->s * A2 + d->r->sz * B2) % mod;
  d->l->A = (d->l->A * A2) % mod;
  d->r->A = (d->r->A * A2) % mod;
  d->l->B = (A2 * d->l->B + B2) % mod;
  d->r->B = (A2 * d->r->B + B2) % mod;
  d->A = 1, d->B = 0;
}
long long sum(int l, int r, int l1, int r1, DO *n) {
  push(n);
  if (l == l1 && r == r1) {
    return n->s;
  }
  int md = (l1 + r1) / 2;
  if (r <= md) return sum(l, r, l1, md, n->l);
  if (l > md) return sum(l, r, md + 1, r1, n->r);
  return (sum(l, md, l1, md, n->l) + sum(md + 1, r, md + 1, r1, n->r)) % mod;
}
void mul2(int l, int r, int l1, int r1, DO *n) {
  push(n);
  if (l == l1 && r == r1) {
    n->s = (n->s * 2) % mod;
    n->A = (n->A * 2) % mod;
    n->B = (n->B * 2) % mod;
    return;
  }
  int md = (l1 + r1) / 2;
  if (r <= md)
    mul2(l, r, l1, md, n->l);
  else if (l > md)
    mul2(l, r, md + 1, r1, n->r);
  else {
    mul2(l, md, l1, md, n->l);
    mul2(md + 1, r, md + 1, r1, n->r);
  }
  UPD(n);
}
void plusplus(int l, int r, int l1, int r1, DO *n) {
  push(n);
  if (l == l1 && r == r1) {
    n->B = (n->B + 1) % mod;
    n->s = (n->s + n->sz) % mod;
    return;
  }
  int md = (l1 + r1) / 2;
  if (r <= md)
    plusplus(l, r, l1, md, n->l);
  else if (l > md)
    plusplus(l, r, md + 1, r1, n->r);
  else {
    plusplus(l, md, l1, md, n->l);
    plusplus(md + 1, r, md + 1, r1, n->r);
  }
  UPD(n);
}
struct Node {
  Node *l = 0, *r = 0;
  pair<int, int> p = {-1, -1};
  Node() {}
  Node(int sz) { p = {0, sz - 1}; }
};
void createL(Node *n, int szL) {
  n->l = new Node(szL);
  if (n->p.first == -1)
    n->l->p = {-1, -1};
  else
    n->l->p = {0, szL - 1};
}
void createR(Node *n, int szR) {
  n->r = new Node(szR);
  if (n->p.first == -1)
    n->r->p = {-1, -1};
  else
    n->r->p = {0, szR - 1};
}
void upd(Node *n, int szL, int szR) {
  pair<int, int> p1 = n->l               ? n->l->p
                      : n->p.first == -1 ? make_pair(-1, -1)
                                         : make_pair(0, szL - 1);
  pair<int, int> p2 = n->r               ? n->r->p
                      : n->p.first == -1 ? make_pair(-1, -1)
                                         : make_pair(0, szR - 1);
  if (p1.first != -1)
    n->p = p1;
  else if (p2.first != -1)
    n->p = {p2.first + szL, p2.second + szL};
  else
    n->p = {-1, -1};
}
vector<pair<int, int> > otr;
Node *DEL0(int l, int r, int l1, int r1, Node *n) {
  if (l == l1 && r == r1) {
    n->p = {-1, -1};
    return n;
  }
  int md = (l1 + r1) / 2;
  if (r <= md) {
    if (!n->l) n->l = new Node(md - l1 + 1), n->l->p = {-1, -1};
    n->l = DEL0(l, r, l1, md, n->l);
  } else if (l > md) {
    if (!n->r) n->r = new Node(r1 - md), n->r->p = {-1, -1};
    n->r = DEL0(l, r, md + 1, r1, n->r);
  } else {
    if (!n->l) n->l = new Node(md - l1 + 1), n->l->p = {-1, -1};
    if (!n->r) n->r = new Node(r1 - md), n->r->p = {-1, -1};
    n->l = DEL0(l, md, l1, md, n->l);
    n->r = DEL0(md + 1, r, md + 1, r1, n->r);
  }
  upd(n, md - l1 + 1, r1 - md);
  return n;
}
Node *set1(int l, int r, int l1, int r1, Node *n) {
  if (l == l1 && r == r1) {
    for (; n->p.first != -1;) {
      otr.push_back({l1 + n->p.first, l1 + n->p.second});
      n = DEL0(n->p.first, n->p.second, 0, r - l, n);
    }
    return n;
  }
  int md = (l1 + r1) / 2;
  if (r <= md) {
    if (!n->l) createL(n, md - l1 + 1);
    n->l = set1(l, r, l1, md, n->l);
  } else if (l > md) {
    if (!n->r) createR(n, r1 - md);
    n->r = set1(l, r, md + 1, r1, n->r);
  } else {
    if (!n->l) createL(n, md - l1 + 1);
    if (!n->r) createR(n, r1 - md);
    n->l = set1(l, md, l1, md, n->l);
    n->r = set1(md + 1, r, md + 1, r1, n->r);
  }
  upd(n, md - l1 + 1, r1 - md);
  return n;
}
int a, z;
vector<Node *> store;
int main() {
  cin.tie(0);
  cout.tie(0);
  cin.sync_with_stdio(0);
  cout.sync_with_stdio(0);
  ;
  cin >> a >> z;
  store = vector<Node *>(a);
  for (int q = 0; q < a; q++) store[q] = new Node(a);
  DO *pizdos_raznos = build(0, a - 1);
  for (int i = 0; i < z; i++) {
    int t, l, r;
    cin >> t >> l >> r;
    l--, r--;
    if (t == 1) {
      int x;
      cin >> x;
      x--;
      store[x] = set1(l, r, 0, a - 1, store[x]);
      int L = l;
      vector<pair<int, int> > notr;
      for (pair<int, int> p : otr) {
        if (p.first > L) notr.push_back({L, p.first - 1});
        L = p.second + 1;
        plusplus(p.first, p.second, 0, a - 1, pizdos_raznos);
      }
      if (L <= r) notr.push_back({L, r});
      for (pair<int, int> p : notr) {
        mul2(p.first, p.second, 0, a - 1, pizdos_raznos);
      }
      notr.clear();
      otr.clear();
    } else {
      long long o = sum(l, r, 0, a - 1, pizdos_raznos);
      cout << o << "\n";
    }
  }
}
