#include <bits/stdc++.h>   using namespace std;   int add(int x, int y) { return ((x + y) % 998244353 + 998244353) % 998244353; }   int mul(int x, int y) { return (long long)x * y % 998244353; }   int mypow(int x, int c) {     int ret = 1;     while (c > 0) {       if (c & 1) {         ret = mul(ret, x);       }       c /= 2;       x = mul(x, x);     }     return ret;   }   int seg[200002 * 4], ad[200002 * 4], mm[200002 * 4];   void init(int pos, int l, int r) {     mm[pos] = 1;     if (l == r) {       return;     }     int mid = (l + r) / 2;     init(pos * 2, l, mid);     init(pos * 2 + 1, mid + 1, r);   }   void push(int pos, int l, int r) {     seg[pos] = mul(seg[pos], mm[pos]);     seg[pos] = add(seg[pos], mul(r - l + 1, ad[pos]));     if (l != r) {       mm[pos * 2] = mul(mm[pos], mm[pos * 2]);       mm[pos * 2 + 1] = mul(mm[pos], mm[pos * 2 + 1]);       ad[pos * 2] = add(mul(ad[pos * 2], mm[pos]), ad[pos]);       ad[pos * 2 + 1] = add(mul(ad[pos * 2 + 1], mm[pos]), ad[pos]);     }     mm[pos] = 1;     ad[pos] = 0;   }   void update(int pos, int l, int r, int ql, int qr, int m, int a) {     push(pos, l, r);     if (r < ql || qr < l) {       return;     }     if (ql <= l && r <= qr) {       mm[pos] = mul(mm[pos], m);       ad[pos] = add(mul(m, ad[pos]), a);       push(pos, l, r);       return;     }     int mid = (l + r) / 2;     update(pos * 2, l, mid, ql, qr, m, a);     update(pos * 2 + 1, mid + 1, r, ql, qr, m, a);     seg[pos] = add(seg[pos * 2], seg[pos * 2 + 1]);   }   int query(int pos, int l, int r, int ql, int qr) {     push(pos, l, r);     if (r < ql || qr < l) {       return 0;     }     if (ql <= l && r <= qr) {       return seg[pos];     }     int mid = (l + r) / 2;     return add(query(pos * 2, l, mid, ql, qr),                query(pos * 2 + 1, mid + 1, r, ql, qr));   }   set<pair<int, int> > s[200002];   void solve() {     int n, q;     scanf( %d %d  , &n, &q);     init(1, 1, n);     for (int i = n; i; --i) {       s[i].insert({n + 2, 0});     }     while (q--) {       int type, l, r;       scanf( %d %d %d  , &type, &l, &r);       if (type == 1) {         int x;         scanf( %d  , &x);         int ml = l, mr = r;         int cur = l;         set<pair<int, int> >::iterator it = s[x].lower_bound({l + 1, 0});         if (it != s[x].begin()) {           it = prev(it);           pair<int, int> t = *it;           if (t.second + 1 >= l) {             ml = min(ml, t.first);             mr = max(mr, t.second);             s[x].erase(it);             update(1, 1, n, l, min(r, t.second), 2, 0);             cur = t.second + 1;           }         }         while (true) {           set<pair<int, int> >::iterator it = s[x].lower_bound({cur, 0});           pair<int, int> tmp = *it;           if (tmp.first <= r + 1) {             if (cur < tmp.first) {               update(1, 1, n, cur, min(r, tmp.first - 1), 1, 1);             }             if (tmp.first <= r) {               update(1, 1, n, tmp.first, min(tmp.second, r), 2, 0);             }             cur = tmp.second + 1;             mr = max(mr, tmp.second);             s[x].erase(it);           } else {             if (cur <= r) {               update(1, 1, n, cur, r, 1, 1);             }             break;           }         }         s[x].insert({ml, mr});       } else {         printf( %d n , query(1, 1, n, l, r));       }     }   }   int main() {     solve();     return 0;   }