#include <bits/stdc++.h>
using namespace std;
set<pair<long long, long long> > con[200005];
int N, Q;
class SegTree {
 private:
  pair<long long, long long> lazy[4 * 200005];
  long long tree[4 * 200005];

 public:
  SegTree() {
    for (int i = 0; i < 4 * 200005; i++) {
      lazy[i].first = 1;
      lazy[i].second = 0;
    }
  }
  long long get_val(long long l, long long r, long long l1, long long r1,
                    long long ind) {
    if (l1 > r || r1 < l) {
      return (0ll);
    }
    if (l <= l1 && r1 <= r) {
      return (tree[ind]);
    }
    if (lazy[ind].first > 1 || lazy[ind].second) {
      lazy[2 * ind].first *= lazy[ind].first;
      lazy[2 * ind].first %= 998244353;
      lazy[2 * ind].second *= lazy[ind].first;
      lazy[2 * ind].second %= 998244353;
      lazy[2 * ind].second += lazy[ind].second;
      tree[2 * ind] = (tree[2 * ind] * lazy[ind].first) % 998244353;
      tree[2 * ind] +=
          (((l1 + r1) / 2 - l1 + 1) * lazy[ind].second) % 998244353;
      lazy[2 * ind + 1].first *= lazy[ind].first;
      lazy[2 * ind + 1].first %= 998244353;
      lazy[2 * ind + 1].second *= lazy[ind].first;
      lazy[2 * ind + 1].second %= 998244353;
      lazy[2 * ind + 1].second += lazy[ind].second;
      tree[2 * ind + 1] = (tree[2 * ind + 1] * lazy[ind].first) % 998244353;
      tree[2 * ind + 1] +=
          ((r1 - ((r1 + l1) / 2)) * lazy[ind].second) % 998244353;
      lazy[ind].first = 1;
      lazy[ind].second = 0;
    }
    long long leftS = get_val(l, r, l1, (r1 + l1) / 2, (2 * ind));
    long long rightS = get_val(l, r, (r1 + l1) / 2 + 1, r1, 2 * ind + 1);
    return ((leftS + rightS) % 998244353);
  }
  long long query(long long a, long long b) { return (get_val(a, b, 0, N, 1)); }
  void change_val(long long l, long long r, int nv1, int nv2, long long ind,
                  long long a, long long b) {
    if (l > b || r < a) {
      return;
    }
    if (a <= l && r <= b) {
      lazy[ind].first *= nv1;
      lazy[ind].first %= 998244353;
      lazy[ind].second *= nv1;
      lazy[ind].second %= 998244353;
      lazy[ind].second += nv2;
      tree[ind] = (tree[ind] * nv1) % 998244353;
      tree[ind] += (r - l + 1) * nv2;
      return;
    }
    if (lazy[ind].first > 1 || lazy[ind].second) {
      lazy[2 * ind].first *= lazy[ind].first;
      lazy[2 * ind].first %= 998244353;
      lazy[2 * ind].second *= lazy[ind].first;
      lazy[2 * ind].second %= 998244353;
      lazy[2 * ind].second += lazy[ind].second;
      tree[2 * ind] = (tree[2 * ind] * lazy[ind].first) % 998244353;
      tree[2 * ind] += (((l + r) / 2 - l + 1) * lazy[ind].second) % 998244353;
      lazy[2 * ind + 1].first *= lazy[ind].first;
      lazy[2 * ind + 1].first %= 998244353;
      lazy[2 * ind + 1].second *= lazy[ind].first;
      lazy[2 * ind + 1].second %= 998244353;
      lazy[2 * ind + 1].second += lazy[ind].second;
      tree[2 * ind + 1] = (tree[2 * ind + 1] * lazy[ind].first) % 998244353;
      tree[2 * ind + 1] += ((r - ((r + l) / 2)) * lazy[ind].second) % 998244353;
      lazy[ind].first = 1;
      lazy[ind].second = 0;
    }
    change_val(l, (r + l) / 2, nv1, nv2, 2 * ind, a, b);
    change_val((r + l) / 2 + 1, r, nv1, nv2, 2 * ind + 1, a, b);
    tree[ind] = (tree[2 * ind] + tree[2 * ind + 1]) % 998244353;
  }
  void update(long long a, long long b, int v1, int v2) {
    change_val(0, N, v1, v2, 1, a, b);
  }
};
SegTree seg;
void update(long long l, long long r, int x) {
  set<pair<long long, long long> > &segments = con[x];
  set<pair<long long, long long> >::iterator it =
      segments.lower_bound(pair<long long, long long>(l, 0));
  --it;
  for (; it != segments.end() && it->first <= r; ++it) {
    int ql = max(l, it->first);
    int qr = min(r, it->second);
    if (ql <= qr) {
      seg.update(ql, qr, 2, 0);
    }
    set<pair<long long, long long> >::iterator nit = ++it;
    --it;
    ql = max(l, it->second + 1);
    qr = min(r, nit->first - 1);
    if (ql <= qr) {
      seg.update(ql, qr, 1, 1);
    }
  }
  it = segments.lower_bound(pair<long long, long long>(l, 0));
  if (it != segments.begin()) {
    --it;
  }
  if (it->second < l) {
    ++it;
  }
  while (it != segments.end() && it->first <= r) {
    l = min(l, it->first);
    r = max(r, it->second);
    set<pair<long long, long long> >::iterator nit = ++it;
    segments.erase(--it);
    it = nit;
  }
  segments.insert(pair<long long, long long>(l, r));
}
int main() {
  cin >> N >> Q;
  for (int i = 1; i <= N; i++) {
    con[i].insert(pair<long long, long long>(-1, -1));
    con[i].insert(pair<long long, long long>(N, N));
  }
  int t, l, r, x;
  for (int i = 0; i < Q; i++) {
    cin >> t >> l >> r;
    if (t == 1) {
      cin >> x;
      update(l - 1, r - 1, x);
    } else
      cout << seg.query(l - 1, r - 1) << endl;
  }
  return (0);
}
