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;

delegate T MergeFunction<T>(T v1, T v2, STParams p);
delegate T ResolveFunction<T, U>(T value, U lazyValue, STParams p);

class STParams {
    public int layer;
    public int segsize;
    public int index;

    public STParams(int layer, int segsize, int index) {
        this.layer = layer;
        this.segsize = segsize;
        this.index = index;
    }
}

class LazySegTree<T, U>
{
    public int Count { get; }
    
    int n_layer;
    int[] segsize;
    T[][] data;    
    bool[][] lazy;
    U[][] lazyData;

    MergeFunction<T> merge;
    ResolveFunction<T, U> resolve;
    
    public LazySegTree(int N, MergeFunction<T> merge, ResolveFunction<T, U> resolve, T fill=default(T))
    {
        Count=N;

        this.merge=merge;
        this.resolve=resolve;
        
        n_layer=1;
        for(int k=1; k<N; k<<=1) n_layer+=1;

        segsize = new int[n_layer];
        data = new T[n_layer][];
        lazy = new bool[n_layer][];
        lazyData = new U[n_layer][];
        for(int l=0; l<n_layer; ++l) {
            segsize[l] = 1<<(n_layer-1-l);
            data[l] = new T[1<<l];
            lazy[l] = new bool[1<<l];
            lazyData[l] = new U[1<<l];
            for(int j=0; j<(1<<l); ++j) data[l][j]=fill;
        }
    }

    public void ResolveLazy(int ibgn, int iend, int l=0) {
        int ssize = segsize[l];
        int index = ibgn/ssize;

        if(lazy[l][index]) {
            data[l][index] = resolve(data[l][index], lazyData[l][index], new STParams(layer: l, segsize: ssize, index: index));
            lazy[l][index] = false;
            if(l+1<n_layer) {
                lazyData[l+1][index*2] = lazyData[l+1][index*2+1] = lazyData[l][index];                
                lazy[l+1][index*2] = lazy[l+1][index*2+1] = true;                
            }
        }
        
        if(ibgn%ssize==0 && iend-ibgn==ssize) return;
        
        int imid = ibgn - ibgn%ssize + ssize/2;
        if(iend<=imid || imid<=ibgn){
            ResolveLazy(ibgn, iend, l+1);
        } else {
            ResolveLazy(ibgn, imid, l+1);
            ResolveLazy(imid, iend, l+1);
        }

    }

    public T Query(int ibgn, int iend, int l=0) {
        //if(l==0) ResolveLazy(ibgn, iend);
        
        int ssize = segsize[l];
        int index = ibgn/ssize;

        if(lazy[l][index]) {
            data[l][index] = resolve(data[l][index], lazyData[l][index], new STParams(layer: l, segsize: ssize, index: index));
            lazy[l][index] = false;
            if(l+1<n_layer) {
                lazyData[l+1][index*2] = lazyData[l+1][index*2+1] = lazyData[l][index];                
                lazy[l+1][index*2] = lazy[l+1][index*2+1] = true;                
            }
        }        
        
        if(ibgn%ssize==0 && iend-ibgn==ssize) return data[l][index];

        int imid = ibgn - ibgn%ssize + ssize/2;
        if(iend<=imid || imid<=ibgn) return Query(ibgn, iend, l+1);
        return merge(Query(ibgn, imid, l+1),
                     Query(imid, iend, l+1),
                     new STParams(layer: l, segsize: ssize, index: index));
    }
    
    public void Update(int ibgn, int iend, U value, int l=0) {
        if(l==0) ResolveLazy(ibgn, iend);
        
        int ssize = segsize[l];
        int index = ibgn/ssize;
        
        if(ibgn%ssize==0 && iend-ibgn==ssize) {
            if(l+1<n_layer){
                lazyData[l+1][index*2] = lazyData[l+1][index*2+1] = value;
                lazy[l+1][index*2] = lazy[l+1][index*2+1] = true;
            }
            data[l][index] = resolve(data[l][index], value, new STParams(layer: l, segsize: ssize, index: index));
        }else{
            int imid = ibgn - ibgn%ssize + ssize/2;
            if(iend<=imid || imid<=ibgn){
                Update(ibgn, iend, value, l+1);
            } else {
                Update(ibgn, imid, value, l+1);
                Update(imid, iend, value, l+1);
            }
            //data[l][index] = merge(data[l+1][index*2], data[l+1][index*2+1], new STParams(layer: l, segsize: ssize, index: index));
            data[l][index] = merge(Query(imid-ssize/2, imid, l+1), Query(imid, imid+ssize/2, l+1), new STParams(layer: l, segsize: ssize, index: index));
        }
    }
    

    public void Print()
    {
        Console.WriteLine($"Count   : {Count}");
        Console.WriteLine($"n_layer : {n_layer}");
        for(int l=0; l<n_layer; ++l) {
            var items = new String[data[l].Length];
            for(int i=0; i<data[l].Length; ++i) {
                items[i] = lazy[l][i] ? $"{data[l][i]}({lazyData[l][i]})" : $"{data[l][i]}";
            }
            Console.WriteLine($"[{l}] "+string.Join(" ", items));
        }
    }
}

class Program
{
    static long mod = 998244353;
    static long[] S;
    
    static long merge(long x, long y, STParams p) { return (x+y)%mod; }
    static long resolve(long value, long lazyValue, STParams p) {
        var ibgn = p.index*p.segsize;
        var iend = ibgn+p.segsize;
        return lazyValue*(S[iend]-S[ibgn]+mod)%mod;
    }
    
    static void Main()
    {
        var str = Console.ReadLine().Split(' ');
        int N = int.Parse(str[0]), Q = int.Parse(str[1]);
        
        S = new long[N+1];
        for(int i=0; i<N; ++i) S[i+1] = (S[i]*10+1)%mod;
        
        var st = new LazySegTree<long, long>(N, merge, resolve);
        st.Update(0, N, 1);

        for(int q=0; q<Q; ++q) {
            str = Console.ReadLine().Split(' ');
            int L = int.Parse(str[0]), R = int.Parse(str[1]), D = int.Parse(str[2]);
            st.Update(N-R, N-L+1, D);
            Console.WriteLine(st.Query(0, N));
        }
    }
}