Problem:
Score : 500 points

Problem Statement

You have a string S of length N.
Initially, all characters in S are 1s.

You will perform queries Q times.
In the i-th query, you are given two integers L_i, R_i and a character D_i (which is a digit).
Then, you must replace all characters from the L_i-th to the R_i-th (inclusive) with D_i.

After each query, read the string S as a decimal integer, and print its value modulo 998,244,353.

Constraints

1 \leq N, Q \leq 200,000

1 \leq L_i \leq R_i \leq N

1 \leq D_i \leq 9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N Q
L_1 R_1 D_1
:
L_Q R_Q D_Q

Output

Print Q lines.
In the i-th line print the value of S after the i-th query, modulo 998,244,353.

Sample Input 1

8 5
3 6 2
1 4 7
3 8 3
2 2 2
4 5 1

Sample Output 1

11222211
77772211
77333333
72333333
72311333

Sample Input 2

200000 1
123 456 7

Sample Output 2

641437905

Don't forget to take the modulo.

Solution in Rust (1.42.0) (judge verdict: Accepted)

const MOD: i64 = 998244353;
const INV9: i64 = 443664157;

fn main() {
	let mut s = String::new();
	use std::io::Read;
	std::io::stdin().read_to_string(&mut s).unwrap();
	let mut s = s.split_whitespace();
	let n: usize = s.next().unwrap().parse().unwrap();
	let tenp = {
		let mut r = vec![1];
		for i in 1..=n + 5 {
			let x = r[i - 1] * 10 % MOD;
			r.push(x);
		}
		r
	};
	let a = vec![(1, 1); n];
	let mut st = LazySegmentTree::construct(
		a,
		(0, 0),
		|a, b| ((a.0 * tenp[b.1] + b.0) % MOD, a.1 + b.1),
		|a, b| (b * (tenp[a.1] + MOD - 1) % MOD * INV9 % MOD, a.1),
		|_, b| b,
	);
	let q: usize = s.next().unwrap().parse().unwrap();
	use std::io::Write;
	let out = std::io::stdout();
	let mut out = std::io::BufWriter::new(out.lock());
	for _ in 0..q {
		let l = s.next().unwrap().parse::<usize>().unwrap() - 1;
		let r: usize = s.next().unwrap().parse().unwrap();
		let d: i64 = s.next().unwrap().parse().unwrap();
		st.operate(l, r, d);
		writeln!(out, "{}", st.fold(0, n).0).unwrap();
	}
}

pub struct LazySegmentTree<M, P, F, G, H> {
	n: usize,
	data: Vec<M>,
	cache: Vec<Option<P>>,
	e: M,
	mfold: F,
	op: G,
	opfold: H,
}

impl<M, P, F, G, H> LazySegmentTree<M, P, F, G, H>
where
	M: Clone,
	P: Clone,
	F: Fn(M, M) -> M,
	G: Fn(M, P) -> M,
	H: Fn(P, P) -> P,
{
	pub fn new(n: usize, e: M, mfold: F, op: G, opfold: H) -> Self {
		Self {
			n,
			data: vec![e.clone(); 2 * n],
			cache: vec![None; 2 * n],
			e,
			mfold,
			op,
			opfold,
		}
	}

	pub fn construct(src: Vec<M>, e: M, mfold: F, op: G, opfold: H) -> Self {
		let mut data = vec![e.clone(); src.len()];
		data.extend(src);
		for i in (1..data.len() / 2).rev() {
			data[i] = mfold(data[i << 1].clone(), data[i << 1 | 1].clone());
		}
		let cache = vec![None; data.len()];
		Self {
			n: data.len() / 2,
			data,
			cache,
			e,
			mfold,
			op,
			opfold,
		}
	}

	fn from_ancestors(&mut self, i: usize) {
		let log2 = (i + 1).next_power_of_two().trailing_zeros() - 1;
		for j in (1..=log2).rev() {
			let i = i >> j;
			if let Some(p) = self.cache[i].take() {
				self.data[i] = (self.op)(self.data[i].clone(), p.clone());
				if let Some(child) = self.cache[i << 1].take() {
					self.cache[i << 1] = Some((self.opfold)(child, p.clone()));
				} else {
					self.cache[i << 1] = Some(p.clone());
				}
				if let Some(child) = self.cache[i << 1 | 1].take() {
					self.cache[i << 1 | 1] = Some((self.opfold)(child, p.clone()));
				} else {
					self.cache[i << 1 | 1] = Some(p.clone());
				}
			}
		}
	}

	fn to_ancestors(&mut self, mut i: usize) {
		while {
			i >>= 1;
			i > 0
		} {
			let s = self.operate_at(i << 1);
			let t = self.operate_at(i << 1 | 1);
			self.data[i] = (self.mfold)(s, t);
		}
	}

	fn operate_at(&self, i: usize) -> M {
		if let Some(p) = self.cache[i].as_ref() {
			(self.op)(self.data[i].clone(), p.clone())
		} else {
			self.data[i].clone()
		}
	}

	pub fn operate(&mut self, l: usize, r: usize, x: P) {
		let mut l = l + self.n;
		let mut r = r + self.n;
		let ltop = l >> l.trailing_zeros();
		let rtop = r >> r.trailing_zeros();
		self.from_ancestors(ltop);
		self.from_ancestors(rtop);
		while l < r {
			if l & 1 != 0 {
				if let Some(p) = self.cache[l].take() {
					self.cache[l] = Some((self.opfold)(p, x.clone()));
				} else {
					self.cache[l] = Some(x.clone());
				}
				l += 1;
			}
			if r & 1 != 0 {
				if let Some(p) = self.cache[r - 1].take() {
					self.cache[r - 1] = Some((self.opfold)(p, x.clone()));
				} else {
					self.cache[r - 1] = Some(x.clone());
				}
			}
			l >>= 1;
			r >>= 1;
		}
		self.to_ancestors(ltop);
		self.to_ancestors(rtop);
	}

	pub fn fold(&mut self, l: usize, r: usize) -> M {
		let mut l = l + self.n;
		let mut r = r + self.n;
		let ltop = l >> l.trailing_zeros();
		let rtop = r >> r.trailing_zeros();
		self.from_ancestors(ltop);
		self.from_ancestors(rtop);
		let mut s = self.e.clone();
		let mut t = self.e.clone();
		while l < r {
			if l & 1 != 0 {
				s = (self.mfold)(s, self.operate_at(l));
				l += 1;
			}
			if r & 1 != 0 {
				t = (self.mfold)(self.operate_at(r - 1), t);
			}
			l >>= 1;
			r >>= 1;
		}
		(self.mfold)(s, t)
	}

	pub fn get(&mut self, i: usize) -> Option<M> {
		if i < self.n {
			Some(self.fold(i, i + 1))
		} else {
			None
		}
	}

	pub fn set(&mut self, i: usize, x: M) {
		let i = i + self.n;
		self.from_ancestors(i);
		self.data[i] = x;
		self.cache[i] = None;
		self.to_ancestors(i);
	}

	pub fn len(&self) -> usize {
		self.n
	}
}