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 C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class TEST{
	static void Main(){
		Sol mySol =new Sol();
		mySol.Solve();
	}
}

class Sol{
	public void Solve(){
		
		int[] a = new int[N];
		for(int i=0;i<N;i++) a[i] = 1;
		var ST = new SegTree(N, a);
		
		//ST.DumpData();
		//ST.DumpLazy();
		
		var sb = new StringBuilder();
		for(int q=0;q<Q;q++){
			int l = L[q], r = R[q], d = D[q];
			ST.UpdateLazy(l, r+1, d);

			//ST.DumpData();
			//ST.DumpLazy();

			var tot = ST.Query(0, N);
			sb.AppendLine(tot.ToString());
		}
		Console.Write(sb.ToString());
		
	}
	int N,Q;
	int[] L,R,D;
	public Sol(){
		var d = ria();
		N = d[0]; Q = d[1];
		L = new int[Q];
		R = new int[Q];
		D = new int[Q];
		for(int i=0;i<Q;i++){
			d = ria();
			L[i] = d[0] - 1;
			R[i] = d[1] - 1;
			D[i] = d[2];
		}
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}


class SegTree{
	//segment Tree 
	// 0-origin
	mlong[] Data;	
	int[] Lazy;
	int[] LenL,LenR;
	protected int N;		
	protected int n;		
	
	mlong[][] V;
	mlong[] Pow10;
	
	public SegTree(int n_, int[] a){
		N = n_;
		n = 1;
		while(n < n_) n *= 2;
		Data = new mlong[2 * n - 1];
		Lazy = new int[2 * n - 1];
		for(int i=0;i<2 * n - 1;i++) Lazy[i] = -1;
		LenL = new int[2 * n - 1];
		LenR = new int[2 * n - 1];
		for(int i=0;i<N;i++){
			LenL[n - 1 + i] = N - 1 - i;
			LenR[n - 1 + i] = N - 1 - i;
		}
		for(int k=n-1-1;k>=0;k--){
			LenL[k] = Math.Min(LenL[2*k+1], LenL[2*k+2]);
			LenR[k] = Math.Max(LenR[2*k+1], LenR[2*k+2]);
		}
		
		V = new mlong[10][];
		for(int i=0;i<10;i++){
			V[i] = new mlong[N + 10];
			V[i][0] = 0;
			for(int j=1;j<N+10;j++){
				V[i][j] = V[i][j-1] * 10 + i;
			}
		}
		//for(int i=0;i<10;i++) Console.WriteLine("V[{0}]: {1},...",i, String.Join(",",V[i].Take(10)));
		
		Pow10 = new mlong[N + 10];
		Pow10[0] = 1;
		for(int i=1;i<N+10;i++){
			Pow10[i] = Pow10[i-1] * 10;
		}
		for(int i=0;i<N;i++){
			Data[i + n - 1] = a[i];
		}
		for(int k=n-1-1;k>=0;k--){
			
			mlong val = Data[2*k+2];
			val += Pow10[LenL[2*k+1] - LenL[2*k+2]] * Data[2*k+1];
			Data[k] = val;
		}
		
	}
	
	public void Eval(int k, int l, int r){
		if(Lazy[k] != -1){
			mlong val = V[Lazy[k]][LenR[k] - LenL[k] + 1];
			Data[k] = val;
			
			if(r - l > 1){
				Lazy[k*2+1] = Lazy[k];
				Lazy[k*2+2] = Lazy[k];
			}
		}
		Lazy[k] = -1;
	}
	public void UpdateLazy(int a, int b, int v){
		UpdateLazy(a, b, v, 0, 0, n);
	}
	public void UpdateLazy(int a, int b, int v, int k, int l, int r){
		Eval(k, l, r);
		if(b <= l || r <= a) return;
		if(a <= l && r <= b) {
			Lazy[k] = v;
			Eval(k, l, r);
		} else {
			UpdateLazy(a, b, v, k*2+1, l, (l+r)/2);
			UpdateLazy(a, b, v, k*2+2, (l+r)/2, r);
			mlong val = Data[2*k+2];
			val += Pow10[LenL[2*k+1] - LenL[2*k+2]] * Data[2*k+1];
			Data[k] = val;
		}
	}
	
	public mlong Query(int a, int b){
		return Query(a, b, 0, 0, n);
	}
	public mlong Query(int a, int b, int k, int l, int r){
		Eval(k, l, r);
		if(b <= l || r <= a) return 0;
		if(a <= l && r <= b) {
			Eval(k, l, r);
			return Data[k];
		} else {
			
			mlong val0 = Query(a, b, 2*k+1, l, (l+r)/2);
			mlong val1 = Query(a, b, 2*k+2, (l+r)/2, r);
			mlong val = val1 + Pow10[LenL[2*k+1] - LenL[2*k+2]] * val0;
			return val;
		}
	}
	
	
	public void Dump<T>(T[] arr){
		Console.WriteLine();
		int h = 0;
		int cnt = 0;
		for(int i=0;i<arr.Length;i++){
			Console.Write("{0} ", arr[i]);
			cnt++;
			if(cnt == 1 << h){
				cnt = 0;
				h++;
				Console.WriteLine();
			}
		}
	}
	public void DumpData(){ Dump(this.Data);}
	public void DumpLazy(){ Dump(this.Lazy);}
	public void DumpLenL(){ Dump(this.LenL);}
	public void DumpLenR(){ Dump(this.LenR);}
	
}


struct mlong {
	
	const long mod = 998244353;
	long V;
	
	public mlong(long _v = 0){
		V = _v;
	}
	
	public static mlong operator+(mlong a, mlong b){
		var v0 = a.V + b.V; if(v0 >= mod) v0 -= mod;
		return new mlong(v0);
	}
	public static mlong operator-(mlong a, mlong b){
		var v0 = mod + a.V - b.V; if(v0 >= mod) v0 -= mod;
		return new mlong(v0);
	}
	public static mlong operator-(mlong b){
		var v0 = mod - b.V; if(v0 >= mod) v0 -= mod;
		return new mlong(v0);
	}
	public static mlong operator*(mlong a, mlong b){
		var v0 = a.V * b.V; if(v0 >= mod) v0 %= mod;
		return new mlong(v0);
	}
	public static mlong operator/(mlong a, mlong b){
		var v0 = a.V * inv(b.V).V; if(v0 >= mod) v0 %= mod;
		return new mlong(v0);
	}
	
	
	public static mlong inv(long x){
		long a = 0, b = 0, c = 0;
		ExtGCD(x, mod, ref a, ref b, ref c);
		return (mlong)((a + mod) % mod);
	}
	
	public static void ExtGCD(long x, long y, ref long a, ref long b, ref long c){
		long r0 = x; long r1 = y;
		long a0 = 1; long a1 = 0;
		long b0 = 0; long b1 = 1;
		long q1, r2, a2, b2;
		while(r1 > 0){
			q1 = r0 / r1;
			r2 = r0 % r1;
			a2 = a0 - q1 * a1;
			b2 = b0 - q1 * b1;
			r0 = r1; r1 = r2;
			a0 = a1; a1 = a2;
			b0 = b1; b1 = b2;
		}
		c = r0;
		a = a0;
		b = b0;
	}
	
	public static mlong ModPow(mlong a, long k){
		if(k == 0) return (mlong) 1;
		if(a == 0) return (mlong) 0;
		mlong x = a;
		mlong ret = 1;
		while(k > 0){
			if(k % 2 == 1) ret *= x;
			x *= x;
			k >>= 1;
		}
		return ret;
	}
	
	
	public static bool operator == (mlong a, mlong b){
		 return a.Equals(b);
	}
	public static bool operator != (mlong a, mlong b){
		 return !(a == b);
	}
	
	public override bool Equals(System.Object obj){
		if(obj  ==  null) return false;
		mlong p  =  (mlong) obj;
		if((System.Object) p  ==  null) return false;
		return p.V  ==  V;
	}
	public override int GetHashCode(){
		return V.GetHashCode();
	}
	
	public static implicit operator mlong(long n){
		long v = n % mod; if(v < 0) v += mod;
		return new mlong(v);
	}
	public static implicit operator mlong(int n){
		long v = n % mod; if(v < 0) v += mod;
		return new mlong(v);
	}
	public static explicit operator long(mlong n){
		return n.V;
	}
	
	public override String ToString(){
		return V.ToString();
	}
	
	
}