#include <bits/stdc++.h>
using namespace std;
long long tree[900000], lazyadd[900000], nwadd[900000], mul[900000],
    lazymul[900000];
set<pair<int, int> > s[250000];
set<pair<int, int> >::iterator it;
void flash(int node, long long st, long long en) {
  tree[node] = (tree[node] * lazymul[node]) % 998244353;
  tree[node] += ((en - st + 1) * lazyadd[node]) % 998244353;
  nwadd[node] *= lazymul[node];
  nwadd[node] %= 998244353;
  nwadd[node] += lazyadd[node];
  mul[node] *= lazymul[node];
  mul[node] %= 998244353;
  nwadd[node] %= 998244353;
  tree[node] %= 998244353;
  lazyadd[node] = 0;
  lazymul[node] = 1;
  return;
}
void push(int node) {
  lazyadd[node * 2] += (nwadd[node]);
  lazyadd[node * 2 + 1] += (nwadd[node]);
  lazyadd[node * 2] %= 998244353;
  lazyadd[node * 2 + 1] %= 998244353;
  lazymul[node * 2] = (mul[node] * lazymul[node * 2]) % 998244353;
  lazymul[node * 2 + 1] = (mul[node] * lazymul[node * 2 + 1]) % 998244353;
  nwadd[node] = 0;
  mul[node] = 1;
}
void update(int node, int st, int en, int l, int r, int bol) {
  flash(node, st, en);
  if (st > r or en < l) return;
  if (st >= l and en <= r) {
    if (bol == 1) {
      tree[node] += (en - st + 1);
      nwadd[node] += (1);
      tree[node] %= 998244353;
      nwadd[node] %= 998244353;
    } else {
      tree[node] = (tree[node] * 2) % 998244353;
      mul[node] = (mul[node] * 2) % 998244353;
      nwadd[node] = (nwadd[node] * 2) % 998244353;
    }
    return;
  }
  int mid = (st + en) >> 1;
  push(node);
  update(node * 2, st, mid, l, r, bol);
  update(node * 2 + 1, mid + 1, en, l, r, bol);
  tree[node] = (tree[node * 2] + tree[node * 2 + 1]) % 998244353;
}
long long query(int node, int st, int en, int l, int r) {
  flash(node, st, en);
  if (st > r or en < l) return 0;
  if (st >= l and en <= r) {
    return tree[node];
  }
  push(node);
  int mid = (st + en) >> 1;
  long long p = query(node * 2, st, mid, l, r);
  long long q = query(node * 2 + 1, mid + 1, en, l, r);
  return (p + q) % 998244353;
}
int n;
void update(int x, int l, int r, int cs) {
  vector<pair<int, int> > tp;
  pair<int, int> ps, gr;
  gr = make_pair(l, 0);
  int tt = l;
  it = s[x].lower_bound(gr);
  ps = *it;
  if (ps.first == l && ps.second >= r) {
    update(1, 1, n, l, r, 2);
    return;
  }
  it--;
  ps = *it;
  if (ps.second >= r) {
    update(1, 1, n, l, r, 2);
    return;
  }
  tp.clear();
  int st = l, en = r;
  if (ps.second >= l) {
    update(1, 1, n, l, ps.second, 2);
    l = ps.second + 1;
    st = ps.first;
    tp.push_back(ps);
  }
  it++;
  while (it != s[x].end()) {
    ps = *it;
    if ((ps.first) > r) {
      if (l <= r) update(1, 1, n, l, r, 1);
      break;
    }
    if (l <= ps.first - 1) update(1, 1, n, l, ps.first - 1, 1);
    tp.push_back(ps);
    update(1, 1, n, ps.first, min(ps.second, r), 2);
    l = ps.second + 1;
    it++;
    en = max(ps.second, r);
  }
  for (int i = 0; i < tp.size(); i++) {
    s[x].erase(tp[i]);
  }
  s[x].insert(make_pair(st, en));
}
int main() {
  int i, j, k, l, m, ty, cs = 1;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= 850000; i++) {
    lazymul[i] = 1;
    mul[i] = 1;
  }
  for (int i = 1; i <= n; i++) {
    s[i].insert(make_pair(0, 0));
    s[i].insert(make_pair(n + 2, n + 2));
  }
  for (int i = 1; i <= m; i++) {
    cin >> ty;
    if (ty == 1) {
      scanf("%d%d%d", &l, &k, &j);
      update(j, l, k, cs);
      continue;
    }
    scanf("%d%d", &l, &k);
    int ans = query(1, 1, n, l, k);
    printf("%d\n", ans);
  }
}
