#include <bits/stdc++.h>


template<std::uint64_t Mod> struct ModInt{
    using u64=uint64_t;
private:
    u64 a;
public:
    constexpr ModInt(){}
    constexpr ModInt(u64 x=0):a(x%Mod){}

    constexpr u64 &value(){return a;}
    constexpr const u64 &value()const{return a;}


    constexpr ModInt &operator+=(const ModInt rhs){
        a+=rhs.value();
        if(a>=Mod){
            a-=Mod;
        }
        return *this;
    }

    constexpr ModInt &operator-=(const ModInt rhs){
        if(a<rhs.value()){
            a+=Mod;
        }
        a-=rhs.value();
        return *this;
    }

    constexpr ModInt &operator*=(const ModInt rhs){
        a=a*rhs.value()%Mod;
        return *this;
    }

    constexpr ModInt &operator/=(ModInt rhs){
        u64 n=Mod-2;
        while(n>0){
        if((n&1)!=0){//n%2==1
            *this*=rhs;
        }
        rhs*=rhs;
        n=n/2;
        }
        return *this;
    }

    constexpr bool operator==(ModInt rhs){
        return a==rhs.value();
    }

    constexpr ModInt operator+(const ModInt rhs){
        return ModInt(*this)+=rhs;
    }

    constexpr ModInt operator-(const ModInt rhs){
        return ModInt(*this)-=rhs;
    }

    constexpr ModInt operator*(const ModInt rhs){
        return ModInt(*this)*=rhs;
    }

    constexpr ModInt operator/(const ModInt rhs){
        return ModInt(*this)/=rhs;
    }
    constexpr ModInt &operator++(){
        ++a;
        if(a>=Mod){
            a-=Mod;
        }
        return *this;
    }

    constexpr ModInt &operator--(){
        if(a==0){
            a+=Mod;
        }
        --a;
        return *this;
    }

    constexpr ModInt operator- (){
        if(a==0)return ModInt(0);
        else return ModInt(Mod-a);
    }


};

using Mi=ModInt<998244353ull>;

Mi operator"" _mi(unsigned long long n){
    return Mi(n);
}

template <typename T,typename E>
struct LazySegmentTree{
private:
    typedef std::function<T(T,T)> F;
    typedef std::function<T(T,E)> G;
    typedef std::function<E(E,E)> H;
    typedef std::function<E(E,int)> P;
    int n;
    F cal;//function for merge
    G upd;//function for update
    H ecal;//function for evaluate
    P rcal;//function for range calculate
    std::vector<T> init;
    T initv;
    E opinit;
    T outv;
    std::vector<T> node;
    std::vector<E> lazy;
public:


    explicit LazySegmentTree(//特定の要素で初期化する場合
            int sz,
            F cal,
            G upd,
            H ecal,
            P rcal=[](T a,int b){return a;},
            T initv=0,
            E opinit=0,
            T outv=0
    ):
    cal(cal),
    upd(upd),
    ecal(ecal),
    rcal(rcal),
    initv(initv),
    opinit(opinit),
    outv(outv)
    {
        n=1;
        while(n<sz)n=n*2;
        node.resize(static_cast<unsigned int>(2 * n - 1), outv);
        for (int i = 0; i <sz ; ++i) node[i+n-1]=initv;
        for (int i = n-2; i >= 0 ; --i) node[i]=cal(node[2*i+1],node[2*i+2]);

        lazy.resize(static_cast<unsigned int>(2 * n - 1), opinit);
        for (int i = 0; i <sz ; ++i) lazy[i+n-1]=opinit;
        for (int i = n-2; i >= 0 ; --i) lazy[i]=ecal(lazy[2*i+1],lazy[2*i+2]);
    }

    void update(int p,int q,E val,int k=0,int l=0,int r=-1){//[p,q):0-indexed
        if(r<0)r=n;
        eval(k,r-l);
        if(r<=p||l>=q)return;
        if(p<=l&&r<=q){
            lazy[k]=ecal(lazy[k],val);
            eval(k,r-l);
        }
        else{
            update(p,q,val,2*k+1,l,(l+r)/2);
            update(p,q,val,2*k+2,(l+r)/2,r);
            node[k]=cal(node[2*k+1],node[2*k+2]);
        }
    }

    T query(int p,int q,int k=0,int l=0,int r=-1){//[p,q):0-indexed
        if(r<0)r=n;
        if(r<=p||l>=q)return outv;

        eval(k,r-l);
        if(p<=l&&r<=q)return node[k];
        T vl=query(p,q,2*k+1,l,(l+r)/2);
        T vr=query(p,q,2*k+2,(l+r)/2,r);
        return cal(vl,vr);
    }

    void eval(int k,int len){//k:0-indexed
        if(lazy[k]==opinit)return;
        node[k]=upd(node[k],rcal(lazy[k],len));
        if(k<n-1){
            lazy[2*k+1]=ecal(lazy[2*k+1],lazy[k]);
            lazy[2*k+2]=ecal(lazy[2*k+2],lazy[k]);
        }
        lazy[k]=opinit;
    }
};

using namespace std;
using ll = long long;

int main() {
    int n,q;
    cin>>n>>q;
    Mi t=1_mi;
    vector<Mi> pt(n+1,1_mi);
    vector<Mi> rpt(n+1,1_mi);
    for(int i = 0;i < n;++i) {
        t*=10;
        pt[i+1]=t;
        rpt[i+1]=t;
        rpt[i+1]+=rpt[i];
    }
    using pmi = pair<Mi,int>;
    LazySegmentTree<pmi,Mi> st(
        n,
        [&](pmi a,pmi b){return pmi(a.first*pt[b.second]+b.first,a.second+b.second);},
        [](pmi a,Mi b){a.first=b; return a;},
        [](Mi a,Mi b){return b;},
        [&](Mi a,int b){return a*rpt[b-1];},
        pmi(1_mi,1),
        0LL,
        pmi(0_mi,0)
    );
    for(int i = 0;i < q;++i) {
        int l,r;
        ll d;
        cin>>l>>r>>d;
        st.update(l-1,r,d);
        cout<<st.query(0,n).first.value()<<endl;
    }
    return 0;
}


Measured memory_bytes: 18504