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++ (GCC 9.2.1) (judge verdict: Accepted)

#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<unordered_set>
#include<unordered_map>
#define ll long long 
#define lowbit(x) (x)&(-x)
using namespace std;
const int maxn = 2e5 + 100;
const ll mod = 998244353;
ll d[maxn];

//线段树
class SEGEMENT_TREE
{
public:
	ll a[maxn];
	struct node
	{
		int L; int R; ll sum; ll flag;
	};
	node tree[maxn << 2];

	//如果某项不需要，为节省事件开销可以注释掉
	void push_down(int x)
	{
		if (tree[x].flag == 0) return;
		tree[x << 1].flag = tree[x].flag; tree[x << 1 | 1].flag = tree[x].flag;
		tree[x << 1].sum = ((d[tree[x << 1].R] - d[tree[x << 1].L - 1]) % mod + mod) % mod * tree[x].flag;
		tree[x << 1].sum %= mod;
		tree[x << 1 | 1].sum = ((d[tree[x << 1 | 1].R] - d[tree[x << 1 | 1].L - 1]) % mod + mod) % mod * tree[x].flag;
		tree[x << 1 | 1].sum %= mod;
		tree[x].flag = 0;
	}

	void push_up(int x)
	{
		tree[x].sum = (tree[x << 1].sum + tree[x << 1 | 1].sum) % mod;
	}

	//最大值和最小值的初值根据实际情况初始化
	//也可以根据初始数组a来进行建树
	void init(int L, int R, int x)
	{
		tree[x].L = L; tree[x].R = R;
		if (tree[x].L == tree[x].R)
		{
			tree[x].sum = ((d[tree[x].R] - d[tree[x].L - 1]) % mod + mod) % mod;
			tree[x].flag = 0;
			return;
		}
		int mid = (L + R) >> 1;
		init(L, mid, x << 1); init(mid + 1, R, x << 1 | 1);
		push_up(x);
	}

	//给l，r区间修改K
	void update(int l, int r, int x, ll K)
	{
		if (l <= tree[x].L && tree[x].R <= r)
		{
			tree[x].sum = ((d[tree[x].R] - d[tree[x].L - 1]) % mod + mod) % mod * K;
			tree[x].sum %= mod;

			tree[x].flag = K;
			return;
		}
		int mid = (tree[x].L + tree[x].R) >> 1;
		push_down(x);
		if (l <= mid) update(l, r, x << 1, K);
		if (mid < r) update(l, r, x << 1 | 1, K);
		push_up(x);
	}
};
//线段树
SEGEMENT_TREE T;

int main()
{
	ios::sync_with_stdio(false);
	int N; cin >> N; int Q; cin >> Q;
	d[1] = 1; d[0] = 0;
	for (int i = 2; i <= N; i++) d[i] = (d[i - 1] * 10) % mod;
	for (int i = 2; i <= N; i++) d[i] = (d[i - 1] + d[i]) % mod;

	T.init(1, N, 1);
	while (Q--)
	{
		int L; int R; ll D; cin >> L >> R >> D;
		//int t = L; L = R; R = t; 
		L = N - L + 1; R = N - R + 1;
		T.update(R, L, 1, D);
		cout << T.tree[1].sum << endl;
	}
	return 0;
}