#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f, oo = inf;
inline long long read() {
  register long long x = 0;
  char f = 0;
  register char c = getchar();
  for (; !isdigit(c); c = getchar()) f |= (c == '-');
  for (; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
  return f ? -x : x;
}
inline double readdb() {
  register double x = 0, p = 0.1;
  register char f = 0, c = getchar();
  for (; !isdigit(c); c = getchar()) f |= (c == '-');
  for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
  if (c == '.')
    for (c = getchar(); isdigit(c); c = getchar(), p /= 10)
      x = x + (c ^ 48) * p;
  return f ? -x : x;
}
inline void write(long long x) {
  if (x < 0) x = -x, putchar('-');
  if (x >= 10) write(x / 10);
  putchar(x % 10 + '0');
}
inline void writeln(long long x) {
  write(x);
  puts("");
}
inline void writeln(long long x, char c, long long y) {
  write(x);
  putchar(c);
  writeln(y);
}
inline void writeln(long long x, char c, long long y, char d, long long z) {
  write(x);
  putchar(c);
  write(y);
  putchar(d);
  writeln(z);
}
const int Mod = 998244353;
const int maxn = 2e5 + 233;
namespace segtree {
int sum[maxn << 2];
int times[maxn << 2], add[maxn << 2];
void update(int o, int l, int r, pair<int, int> v) {
  times[o] = 1ll * times[o] * v.first % Mod;
  add[o] = (1ll * add[o] * v.first + v.second) % Mod;
  sum[o] = (1ll * sum[o] * v.first + 1ll * v.second * (r - l + 1)) % Mod;
}
inline void pushdown(int o, int l, int r) {
  update((o << 1), l, ((l + r) >> 1), {times[o], add[o]});
  update((o << 1 | 1), ((l + r) >> 1) + 1, r, {times[o], add[o]});
  times[o] = 1;
  add[o] = 0;
}
inline void pushup(int o) {
  sum[o] = (sum[(o << 1)] + sum[(o << 1 | 1)]) % Mod;
}
inline void modify(int o, int l, int r, int x, int y, pair<int, int> v) {
  if (l == x && r == y) {
    update(o, l, r, v);
    return;
  }
  pushdown(o, l, r);
  if (y <= ((l + r) >> 1))
    modify((o << 1), l, ((l + r) >> 1), x, y, v);
  else if (((l + r) >> 1) + 1 <= x)
    modify((o << 1 | 1), ((l + r) >> 1) + 1, r, x, y, v);
  else {
    modify((o << 1), l, ((l + r) >> 1), x, ((l + r) >> 1), v);
    modify((o << 1 | 1), ((l + r) >> 1) + 1, r, ((l + r) >> 1) + 1, y, v);
  }
  pushup(o);
}
int query(int o, int l, int r, int x, int y) {
  if (l == x && r == y) return sum[o];
  pushdown(o, l, r);
  if (y <= ((l + r) >> 1))
    return query((o << 1), l, ((l + r) >> 1), x, y);
  else if (((l + r) >> 1) + 1 <= x)
    return query((o << 1 | 1), ((l + r) >> 1) + 1, r, x, y);
  else {
    return (query((o << 1), l, ((l + r) >> 1), x, ((l + r) >> 1)) +
            query((o << 1 | 1), ((l + r) >> 1) + 1, r, ((l + r) >> 1) + 1, y)) %
           Mod;
  }
}
}  // namespace segtree
set<pair<int, int> > s[maxn];
int n, Q;
void split(int x, int l) {
  auto w = s[x].lower_bound({l, l});
  if (w != s[x].begin()) {
    w--;
    int FI = w->first;
    int SE = w->second;
    if (SE >= l) {
      s[x].erase(w);
      s[x].insert({FI, l - 1});
      s[x].insert({l, SE});
    }
  }
}
int main() {
  n = read(), Q = read();
  for (register int i = (1); i <= (n); ++i) s[i].insert({1, n});
  for (register int i = (1); i <= (Q); ++i) {
    int op = read(), l = read(), r = read();
    if (op == 1) {
      int x = read();
      segtree::modify(1, 1, n, l, r, {2, 0});
      split(x, l), split(x, r + 1);
      for (auto w = s[x].lower_bound({l, l});
           w != s[x].end() && (w->second <= r); w = s[x].lower_bound({l, l})) {
        segtree::modify(1, 1, n, w->first, w->second, {(Mod + 1) / 2, 1});
        s[x].erase(w);
      }
    } else {
      writeln(segtree::query(1, 1, n, l, r));
    }
  }
  return 0;
}
