Problem: You are given an array a_0, a_1, ..., a_{N-1} of length N. Process Q queries of the following types.

* `0 l r b c`: For each i = l, l+1, \dots, {r - 1}, set a_i \gets b \times a_i + c.
* `1 l r`: Print \sum_{i = l}^{r - 1} a_i \bmod 998244353.

Constraints

* 1 \leq N, Q \leq 500000
* 0 \leq a_i, c < 998244353
* 1 \leq b < 998244353
* 0 \leq l < r \leq N
* All values in Input are integer.

Input

Input is given from Standard Input in the following format:


N Q
a_0 a_1 ... a_{N - 1}
\textrm{Query}_0
\textrm{Query}_1
:
\textrm{Query}_{Q - 1}


Output

For each query of the latter type, print the answer.

Example

Input

5 7
1 2 3 4 5
1 0 5
0 2 4 100 101
1 0 3
0 1 3 102 103
1 2 5
0 2 5 104 105
1 0 5


Output

15
404
41511
4317767

Solution (in CPP):

Solution:
//#include "bits/stdc++.h"

#define _USE_MATH_DEFINES
#include<cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <deque>
#include <algorithm>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <array>
#include <unordered_map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <iterator>
#include<iomanip>
#include<complex>
#include<assert.h>

using namespace std;

#define rep(i,a,b) for(int i=(a), i##_len=(b);i<i##_len;i++)
#define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--)
#define all(c) begin(c),end(c)

#define int ll
#define SZ(x) ((int)(x).size())
#define pb push_back
#define mp make_pair

//typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, double> pid;
typedef pair<double, int> pdi;
typedef pair<double, double> pdd;
typedef vector< vector<int> > mat;

template<class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template<class T> bool chmin(T &a, const T &b) { if (b < a) { a = b; return true; } return false; }

const int INF = sizeof(int) == sizeof(long long) ? 0x3f3f3f3f3f3f3f3fLL : 0x3f3f3f3f;
//const int MOD = (int)1e9 + 7;
const int MOD = 998244353;

const double EPS = 1e-9;

template <typename T, typename E>
struct LazySegmentTree {
	typedef function<T(T, T)> F;//merge
	typedef function<T(T, E)> G;//dat lazy
	typedef function<E(E, E)> H;//lazy lazy
	typedef function<E(E, int)> P;//lazy len

	vector<T> dat; vector<E> laz;
	int n; F f; G g; H h; P p;
	T d1;//datの単位元
	E d0;//lazyの単位元

	LazySegmentTree(int m, F f, G g, H h, P p, T d1, E d0) : f(f), g(g), h(h), p(p), d1(d1), d0(d0)
	{
		n = 1;
		while (n < m) n *= 2;
		dat.assign(2 * n - 1, d1);
		laz.assign(2 * n - 1, d0);
	}
	
	void init(const vector<T> v)
	{
		for (int i = 0; i < SZ(v); i++) dat[i + n - 1] = v[i];
		for (int i = n - 2; i >= 0; i--) dat[i] = f(dat[i * 2 + 1], dat[i * 2 + 2]);
	}

	inline void eval(int len, int k) 
	{
		if (laz[k] == d0) return;
		if (k * 2 + 1 < n * 2 - 1) 
		{
			laz[k * 2 + 1] = h(laz[k * 2 + 1], laz[k]);
			laz[k * 2 + 2] = h(laz[k * 2 + 2], laz[k]);
		}
		dat[k] = g(dat[k], p(laz[k], len));
		laz[k] = d0;
	}

	void update(int a, int b, E x, int k, int l, int r) 
	{
		eval(r - l, k);
		if (a <= l && r <= b) 
		{
			laz[k] = h(laz[k], x);
			eval(r - l, k);
		}
		else if (a < r&&l < b)
		{
			update(a, b, x, k * 2 + 1, l, (l + r) / 2);
			update(a, b, x, k * 2 + 2, (l + r) / 2, r);

			dat[k] = f(dat[k * 2 + 1], dat[k * 2 + 2]);
		}
	}

	T query(int a, int b, int k, int l, int r)
	{
		eval(r - l, k);
		if (r <= a || b <= l) return d1;
		if (a <= l && r <= b) return dat[k];
		T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
		T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
		return f(vl, vr);
	}

	void update(int a, int b, E x) { update(a, b, x, 0, 0, n); }
	T query(int a, int b) { return query(a, b, 0, 0, n); }
	T operator[](const int &k) const { return dat[k + n - 1]; }
};

signed main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);

	int N, Q;
	cin >> N >> Q;

	auto f = [&](int a, int b) {return (a + b) % MOD; };
	auto g = [&](int a, array<array<int, 2>, 2> b) {return (b[0][0] * a + b[0][1]) % MOD; };
	auto h = [&](array<array<int, 2>, 2> a, array<array<int, 2>, 2> b) 
	{
		array<array<int, 2>, 2> res;
		res[0][0] = b[0][0] * a[0][0] + b[0][1] * a[1][0];
		res[0][1] = b[0][0] * a[0][1] + b[0][1] * a[1][1];
		res[1][0] = b[1][0] * a[0][0] + b[1][1] * a[1][0];
		res[1][1] = b[1][0] * a[0][1] + b[1][1] * a[1][1];
		rep(i, 0, 2)rep(j, 0, 2)res[i][j] %= MOD;
		return res;
	};
	auto p = [&](array<array<int, 2>, 2> a, int b)
	{
		array<array<int, 2>, 2> res;
		res[0][0] = a[0][0];
		res[0][1] = a[0][1] * b;
		res[1][0] = 0LL;
		res[1][1] = 1LL;
		return res;
	};

	array<array<int, 2>, 2> d0;
	d0[0][0] = 1, d0[0][1] = 0;
	d0[1][0] = 0, d0[1][1] = 1;
	LazySegmentTree<int, array<array<int, 2>, 2>> st(N, f, g, h, p, 0LL, d0);

	vector<int> A(N);
	rep(i, 0, N)cin >> A[i];

	st.init(A);

	int t, l, r, x, y;
	rep(i, 0, Q)
	{
		cin >> t;
		if (t == 0)
		{
			cin >> l >> r >> x >> y;
			d0[0][0] = x, d0[0][1] = y;
			d0[1][0] = 0, d0[1][1] = 1;
			st.update(l, r, d0);
		}
		else
		{
			cin >> l >> r;
			cout << st.query(l, r) << endl;
		}
		//cout << "a" << endl;
	}

	return 0;
}