#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
const long long MOD = 998244353;
long long lazyAdd[MAXN << 2];
long long sum[MAXN << 2];
long long lazyMul[MAXN << 2];
int N, Q;
void build(int l, int r, int rt) {
  lazyMul[rt] = 1;
  if (l == r) return;
  int m = (l + r) / 2;
  build(l, m, rt << 1);
  build(m + 1, r, rt << 1 | 1);
}
void pushup(int rt) { sum[rt] = (sum[rt << 1] + sum[rt << 1 | 1]) % MOD; }
void pushdown(int rt, int ln, int rn) {
  if (lazyMul[rt] != 1) {
    sum[rt << 1] = (sum[rt << 1] % MOD * lazyMul[rt] % MOD) % MOD;
    lazyMul[rt << 1] = (lazyMul[rt << 1] % MOD * lazyMul[rt] % MOD) % MOD;
    lazyAdd[rt << 1] = (lazyAdd[rt << 1] % MOD * lazyMul[rt] % MOD) % MOD;
    sum[rt << 1 | 1] = (sum[rt << 1 | 1] % MOD * lazyMul[rt] % MOD) % MOD;
    lazyMul[rt << 1 | 1] =
        (lazyMul[rt << 1 | 1] % MOD * lazyMul[rt] % MOD) % MOD;
    lazyAdd[rt << 1 | 1] =
        (lazyAdd[rt << 1 | 1] % MOD * lazyMul[rt] % MOD) % MOD;
    lazyMul[rt] = 1;
  }
  if (lazyAdd[rt]) {
    sum[rt << 1] = (sum[rt << 1] + lazyAdd[rt] * ln % MOD) % MOD;
    lazyAdd[rt << 1] = (lazyAdd[rt << 1] + lazyAdd[rt] % MOD) % MOD;
    sum[rt << 1 | 1] = (sum[rt << 1 | 1] + lazyAdd[rt] * rn % MOD) % MOD;
    lazyAdd[rt << 1 | 1] = (lazyAdd[rt << 1 | 1] + lazyAdd[rt]) % MOD;
    lazyAdd[rt] = 0;
  }
}
void updateAdd(int L, int R, long long C, int l, int r, int rt) {
  if (L <= l && r <= R) {
    lazyAdd[rt] = (lazyAdd[rt] + C) % MOD;
    sum[rt] = (sum[rt] + C * (r - l + 1) % MOD) % MOD;
    return;
  }
  int m = (l + r) / 2;
  pushdown(rt, m - l + 1, r - m);
  if (L <= m) updateAdd(L, R, C, l, m, rt << 1);
  if (R > m) updateAdd(L, R, C, m + 1, r, rt << 1 | 1);
  pushup(rt);
}
void updateMul(int L, int R, long long C, int l, int r, int rt) {
  if (L <= l && r <= R) {
    lazyMul[rt] = (lazyMul[rt] * C) % MOD;
    lazyAdd[rt] = (lazyAdd[rt] * C) % MOD;
    sum[rt] = (sum[rt] * C) % MOD;
    return;
  }
  int m = (l + r) / 2;
  pushdown(rt, m - l + 1, r - m);
  if (L <= m) updateMul(L, R, C, l, m, rt << 1);
  if (R > m) updateMul(L, R, C, m + 1, r, rt << 1 | 1);
  pushup(rt);
}
long long query(int L, int R, int l, int r, int rt) {
  if (L <= l && r <= R) return sum[rt] % MOD;
  int m = (l + r) / 2;
  pushdown(rt, m - l + 1, r - m);
  long long ans = 0;
  if (L <= m) ans = (ans + query(L, R, l, m, rt << 1)) % MOD;
  if (R > m) ans = (ans + query(L, R, m + 1, r, rt << 1 | 1)) % MOD;
  return ans % MOD;
}
set<pair<int, bool> > S[MAXN];
void update(int l, int r, int w) {
  auto &s = S[w];
  pair<int, bool> node1 = make_pair(l, 0);
  pair<int, bool> node2 = make_pair(r, 1);
  while (l <= r) {
    auto it = s.lower_bound(make_pair(l, 0));
    if (it == s.end()) {
      updateAdd(l, r, 1, 1, N, 1);
      break;
    }
    if (it->second == 1) {
      updateMul(l, min(it->first, r), 2, 1, N, 1);
      l = min(it->first, r) + 1;
      if (r >= it->first) s.erase(it);
    } else {
      if (l <= min(it->first - 1, r))
        updateAdd(l, min(it->first - 1, r), 1, 1, N, 1);
      l = min(it->first - 1, r) + 1;
      if (r >= it->first) s.erase(it);
    }
  }
  auto it = s.lower_bound(node1);
  auto it2 = s.lower_bound(node1);
  if (it == s.begin() || (--it)->second) s.insert(node1);
  if (it2 == s.end() || it2->second == 0) s.insert(node2);
}
int main() {
  scanf("%d%d", &N, &Q);
  build(1, N, 1);
  int op, l, r, w;
  for (int i = 0; i < Q; i++) {
    scanf("%d", &op);
    if (op == 1) {
      scanf("%d%d%d", &l, &r, &w);
      update(l, r, w);
    } else {
      scanf("%d%d", &l, &r);
      printf("%lld\n", query(l, r, 1, N, 1) % MOD);
    }
  }
  return 0;
}
