#include <bits/stdc++.h>
using namespace std;
void doRoutine() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  srand(322179);
}
const long long INF = 1000000000000000000;
const long long MOD = 998244353;
const int MAXN = 200005;
int n, q;
struct State {
  long long val;
  long long k, b;
  State(long long _val = 0, long long _k = 1, long long _b = 0) {
    val = _val, k = _k, b = _b;
  }
};
const int TR_MAX_SZ = MAXN * 4;
State tr[TR_MAX_SZ];
void push(int v, int lb, int rb) {
  long long k = tr[v].k, b = tr[v].b;
  tr[v].val = (k * tr[v].val + tr[v].b * (rb - lb)) % MOD;
  int mb = (lb + rb) / 2;
  if (rb - lb > 1) {
    tr[v * 2 + 1].k *= k;
    tr[v * 2 + 1].b = k * tr[v * 2 + 1].b + b;
    tr[v * 2 + 1].k %= MOD;
    tr[v * 2 + 1].b %= MOD;
    tr[v * 2 + 2].k *= k;
    tr[v * 2 + 2].b = k * tr[v * 2 + 2].b + b;
    tr[v * 2 + 2].k %= MOD;
    tr[v * 2 + 2].b %= MOD;
  }
  tr[v].k = 1, tr[v].b = 0;
}
int real_val(int v, int lb, int rb) {
  return (tr[v].val * tr[v].k + tr[v].b * (rb - lb)) % MOD;
}
long long get_sum(int v, int lb, int rb, int l, int r) {
  if (l == r) {
    return 0;
  }
  push(v, lb, rb);
  if (l == lb && r == rb) {
    return tr[v].val;
  } else {
    int mb = (lb + rb) / 2;
    if (r <= mb) {
      return get_sum(2 * v + 1, lb, mb, l, r);
    } else if (l >= mb) {
      return get_sum(2 * v + 2, mb, rb, l, r);
    } else {
      return (get_sum(2 * v + 1, lb, mb, l, mb) +
              get_sum(2 * v + 2, mb, rb, mb, r)) %
             MOD;
    }
  }
}
void add(int v, int lb, int rb, int l, int r, int x) {
  if (l == r) {
    return;
  }
  push(v, lb, rb);
  if (l == lb && r == rb) {
    tr[v].b += x;
    tr[v].b %= MOD;
  } else {
    int mb = (lb + rb) / 2;
    if (r <= mb) {
      add(v * 2 + 1, lb, mb, l, r, x);
    } else if (l >= mb) {
      add(v * 2 + 2, mb, rb, l, r, x);
    } else {
      add(v * 2 + 1, lb, mb, l, mb, x);
      add(v * 2 + 2, mb, rb, mb, r, x);
    }
    tr[v].val =
        (real_val(2 * v + 1, lb, mb) + real_val(2 * v + 2, mb, rb)) % MOD;
  }
}
void mul(int v, int lb, int rb, int l, int r, int x) {
  if (l == r) {
    return;
  }
  push(v, lb, rb);
  if (l == lb && r == rb) {
    tr[v].k *= x;
    tr[v].b *= x;
    tr[v].k %= MOD;
    tr[v].b %= MOD;
  } else {
    int mb = (lb + rb) / 2;
    if (r <= mb) {
      mul(2 * v + 1, lb, mb, l, r, x);
    } else if (l >= mb) {
      mul(2 * v + 2, mb, rb, l, r, x);
    } else {
      mul(2 * v + 1, lb, mb, l, mb, x);
      mul(2 * v + 2, mb, rb, mb, r, x);
    }
    tr[v].val =
        (real_val(2 * v + 1, lb, mb) + real_val(2 * v + 2, mb, rb)) % MOD;
  }
}
void print(int v, int l, int r) {
  if (v == 0) {
    if (0) cerr << "===== OUTPUT START =====" << endl;
  }
  if (0)
    cerr << "[" << l << ", " << r << "): " << tr[v].val << "; " << tr[v].k
         << ", " << tr[v].b << endl;
  if (l + 1 < r) {
    print(v * 2 + 1, l, (l + r) / 2);
    print(v * 2 + 2, (l + r) / 2, r);
  }
  if (v == 0) {
    if (0) cerr << "===== OUTPUT END =====" << endl;
  }
}
void add_one(int l, int r) {
  if (0) cerr << "add_one: " << l << ", " << r << endl;
  add(0, 0, n, l, r, 1);
}
void mul_twice(int l, int r) {
  if (0) cerr << "mul_twice: " << l << ", " << r << endl;
  mul(0, 0, n, l, r, 2);
}
pair<int, int> intersect(pair<int, int> a, pair<int, int> b) {
  int x = max(a.first, b.first);
  int y = min(a.second, b.second);
  if (x < y) {
    return {x, y};
  } else {
    return {0, 0};
  }
}
set<pair<int, int> > segs[MAXN];
void add_seg(int l, int r, int x) {
  auto it = segs[x].lower_bound({r, -1});
  vector<pair<int, int> > todel;
  int min_left = l, max_right = r;
  while (it != segs[x].begin()) {
    --it;
    if (it->second > l) {
      min_left = min(min_left, it->first);
      max_right = max(max_right, it->second);
      todel.push_back(*it);
    } else {
      break;
    }
  }
  reverse(todel.begin(), todel.end());
  for (auto el : todel) {
    segs[x].erase(el);
  }
  segs[x].insert({min_left, max_right});
  for (auto el : todel) {
    auto seg = intersect(el, {l, r});
    mul_twice(seg.first, seg.second);
  }
  for (int i = 0; i + 1 < todel.size(); ++i) {
    add_one(todel[i].second, todel[i + 1].first);
  }
  if (todel.empty()) {
    add_one(l, r);
  } else {
    if (l < todel[0].first) {
      add_one(l, todel[0].first);
    }
    if (todel.back().second < r) {
      add_one(todel.back().second, r);
    }
  }
}
signed main() {
  doRoutine();
  cin >> n >> q;
  for (int i = 0; i < q; ++i) {
    int t;
    cin >> t;
    if (t == 1) {
      int l, r, x;
      cin >> l >> r >> x;
      --l;
      add_seg(l, r, x);
    } else {
      int l, r;
      cin >> l >> r;
      --l;
      cout << get_sum(0, 0, n, l, r) << endl;
    }
  }
  return 0;
}
