#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
const int Mod = 998244353;
namespace print {
static const int BUF = 50000000;
char buf[BUF], *h = buf;
inline void put(char ch) {
  h == buf + BUF ? (fwrite(buf, 1, BUF, stdout), h = buf) : 0;
  *h++ = ch;
}
inline void putint(int num) {
  static char _buf[30];
  sprintf(_buf, "%d", num);
  for (char *s = _buf; *s; s++) put(*s);
}
inline void finish() { fwrite(buf, 1, h - buf, stdout); }
};  // namespace print
struct Readint {
  char buffer[1 << 15], *S, *T;
  inline char Get_Char() {
    if (S == T) {
      T = (S = buffer) + fread(buffer, 1, 1 << 15, stdin);
      if (S == T) return EOF;
    }
    return *S++;
  }
  int Read() {
    char c;
    int re = 0;
    for (c = Get_Char(); c < '0' || c > '9'; c = Get_Char()) {
      if (c == EOF) return -1;
    }
    while (c >= '0' && c <= '9')
      re = (re << 1) + (re << 3) + (c - '0'), c = Get_Char();
    return re;
  }
} Re;
struct node {
  int p, id;
  bool operator<(const node &u) const { return u.p == p ? id < u.id : p < u.p; }
};
set<node> s[N];
set<node>::iterator it, her;
int sum[N << 2], add[N << 2], mul[N << 2];
int sz[N << 2];
int L, R, w, ans, n, m;
void Add(int x, int k) {
  add[x] += k;
  add[x] -= add[x] >= Mod ? Mod : 0;
  sum[x] += (sz[x] * (long long)k) % Mod;
  sum[x] -= sum[x] >= Mod ? Mod : 0;
}
void Mul(int x, int k) {
  sum[x] = sum[x] * (long long)k % Mod;
  mul[x] = mul[x] * (long long)k % Mod;
  add[x] = add[x] * (long long)k % Mod;
}
void pushdown(int x) {
  if (mul[x] != 1) {
    Mul((x << 1), mul[x]);
    Mul(((x << 1) | 1), mul[x]);
    mul[x] = 1;
  }
  if (add[x]) {
    Add((x << 1), add[x]);
    Add(((x << 1) | 1), add[x]);
    add[x] = 0;
  }
}
void build(int x, int l, int r) {
  mul[x] = 1;
  sz[x] = r - l + 1;
  add[x] = sum[x] = 0;
  if (l == r) return;
  build((x << 1), l, ((l + r) >> 1));
  build(((x << 1) | 1), ((l + r) >> 1) + 1, r);
}
void umul(int x, int l, int r) {
  if (l >= L && r <= R) {
    Mul(x, 2);
    return;
  }
  pushdown(x);
  if (L <= ((l + r) >> 1)) umul((x << 1), l, ((l + r) >> 1));
  if (R > ((l + r) >> 1)) umul(((x << 1) | 1), ((l + r) >> 1) + 1, r);
  sum[x] = (sum[(x << 1)] + sum[((x << 1) | 1)]);
  sum[x] -= sum[x] >= Mod ? Mod : 0;
}
void uadd(int x, int l, int r) {
  if (l >= L && r <= R) {
    Add(x, w);
    return;
  }
  pushdown(x);
  if (L <= ((l + r) >> 1)) uadd((x << 1), l, ((l + r) >> 1));
  if (R > ((l + r) >> 1)) uadd(((x << 1) | 1), ((l + r) >> 1) + 1, r);
  sum[x] = (sum[(x << 1)] + sum[((x << 1) | 1)]);
  sum[x] -= sum[x] >= Mod ? Mod : 0;
}
void query(int x, int l, int r) {
  if (l >= L && r <= R) {
    ans += sum[x];
    ans -= ans >= Mod ? Mod : 0;
    return;
  }
  pushdown(x);
  if (L <= ((l + r) >> 1)) query((x << 1), l, ((l + r) >> 1));
  if (R > ((l + r) >> 1)) query(((x << 1) | 1), ((l + r) >> 1) + 1, r);
}
void solve(int x, int l, int r) {
  set<node> &S = s[x];
  it = S.lower_bound((node){l, 0});
  int fl = L, fr = R;
  for (w = 1; l <= r; it = S.lower_bound((node){l, 0})) {
    if (it == S.end()) {
      L = l;
      R = r;
      uadd(1, 1, n);
      break;
    } else if (it->id) {
      L = l;
      R = min(it->p, r);
      umul(1, 1, n);
      l = R + 1;
      if (r >= it->p) S.erase(it);
    } else {
      L = l;
      R = min(it->p - 1, r);
      if (L <= R) uadd(1, 1, n);
      l = R + 1;
      if (r >= it->p) S.erase(it);
    }
  }
  it = S.lower_bound((node){fl, 0});
  her = S.lower_bound((node){fr, 1});
  if (it == S.begin() || (--it)->id) S.insert((node){fl, 0});
  if (her == S.end() || !her->id) S.insert((node){fr, 1});
}
int main() {
  n = Re.Read();
  m = Re.Read();
  build(1, 1, n);
  while (m--) {
    int opt = Re.Read();
    if (opt == 1) {
      L = Re.Read();
      R = Re.Read();
      w = Re.Read();
      solve(w, L, R);
    } else {
      ans = 0;
      L = Re.Read();
      R = Re.Read();
      query(1, 1, n);
      print::putint(ans);
      print::put('\n');
    }
  }
  print::finish();
  return 0;
}
