description: A matrix of size n × m, such that each cell of it contains either 0 or 1, is considered beautiful if the sum in every contiguous submatrix of size 2 × 2 is exactly 2, i. e. every "square" of size 2 × 2 contains exactly two 1's and exactly two 0's.
  
  You are given a matrix of size n × m. Initially each cell of this matrix is empty. Let's denote the cell on the intersection of the x-th row and the y-th column as (x, y). You have to process the queries of three types:
  
    * x y -1 — clear the cell (x, y), if there was a number in it; 
    * x y 0 — write the number 0 in the cell (x, y), overwriting the number that was there previously (if any); 
    * x y 1 — write the number 1 in the cell (x, y), overwriting the number that was there previously (if any). 
  
  
  
  After each query, print the number of ways to fill the empty cells of the matrix so that the resulting matrix is beautiful. Since the answers can be large, print them modulo 998244353.
  
  Input
  
  The first line contains three integers n, m and k (2 ≤ n, m ≤ 10^6; 1 ≤ k ≤ 3 ⋅ 10^5) — the number of rows in the matrix, the number of columns, and the number of queries, respectively.
  
  Then k lines follow, the i-th of them contains three integers x_i, y_i, t_i (1 ≤ x_i ≤ n; 1 ≤ y_i ≤ m; -1 ≤ t_i ≤ 1) — the parameters for the i-th query.
  
  Output
  
  For each query, print one integer — the number of ways to fill the empty cells of the matrix after the respective query, taken modulo 998244353.
  
  Example
  
  Input
  
  
  2 2 7
  1 1 1
  1 2 1
  2 1 1
  1 1 0
  1 2 -1
  2 1 -1
  1 1 -1
  
  
  Output
  
  
  3
  1
  0
  1
  2
  3
  6
solution: import java.math.*;
  import java.util.*;
  
  public class E {
  
  	public Object solve () {
  		N = sc.nextInt(); M = sc.nextInt(); K = sc.nextInt();
  		int [][] A = sc.nextInts(K);
  
  		int [][] R = new int [2][N];
  		int CR0 = 0, CR2 = N;
  
  		int [][] C = new int [2][M];
  		int CC0 = 0, CC2 = M;
  
  		int [] CD = new int [2];
  
  		Map<Long, Integer> H = new HashMap<>();
  
  		for (int i : rep(K)) {
  			int x = A[i][0] - 1, y = A[i][1] - 1, m = A[i][2];
  
  			long z = key(x, y);
  			Integer v = H.remove(z);
  
  			if (v != null) {
  				if ((--R[(v+y) % 2][x]) == 0)
  					if (R[(v+y+1) % 2][x] == 0)
  						++CR2;
  					else
  						--CR0;
  
  				if ((--C[(v+x) % 2][y]) == 0)
  					if (C[(v+x+1) % 2][y] == 0)
  						++CC2;
  					else
  						--CC0;
  
  				--CD[(v+x+y) % 2];
  			}
  
  			if (m >= 0) {
  				if ((R[(m+y) % 2][x]++) == 0)
  					if (R[(m+y+1) % 2][x] == 0)
  						--CR2;
  					else
  						++CR0;
  
  				if ((C[(m+x) % 2][y]++) == 0)
  					if (C[(m+x+1) % 2][y] == 0)
  						--CC2;
  					else
  						++CC0;
  
  				++CD[(m+x+y) % 2];
  
  				H.put(z, m);
  			}
  
  			long QR = 0, QC = 0, QD = 0;
  			if (CR0 == 0)
  				QR = modPow(2, CR2);
  			if (CC0 == 0)
  				QC = modPow(2, CC2);
  			if (CD[0] == 0 && CD[1] == 0)
  				QD = 2;
  			else if (CD[0] == 0 || CD[1] == 0)
  				QD = 1;
  
  			long res = (QR + QC + MOD - QD) % MOD;
  			print(res);
  		}
  
  		return null;
  	}
  
  	int N, M, K;
  
  	long key (int x, int y) {
  		long res = x * M + y;
  		return res;
  	}
  
  	private static final int CONTEST_TYPE = 1;
  
  	private static void init () {
  	}
  
  	private static final int MOD = 998244353;
  	private static long modPow (long b, long e) { return modPow(b, e, MOD); }
  	private static long modPow (long b, long e, int mod) { return BigInteger.valueOf(b).modPow(BigInteger.valueOf(e), BigInteger.valueOf(mod)).longValue(); }
  	private static int [] rep (int N) { return rep(0, N); }
  	private static int [] rep (int S, int T) { if (S >= T) return new int [0]; int [] res = new int [T-S]; for (int i = S; i < T; ++i) res[i-S] = i; return res; }
  	//////////////////////////////////////////////////////////////////////////////////// OFF
  	private static IOUtils.MyScanner sc = new IOUtils.MyScanner();
  	private static Object print (Object o, Object ... A) { IOUtils.print(o, A); return null; }
  	private static class IOUtils {
  		public static class MyScanner {
  			public String next () { newLine(); return line[index++]; }
  			public int nextInt () { return Integer.parseInt(next()); }
  			public String nextLine () { line = null; return readLine(); }
  			public String [] nextStrings () { return split(nextLine()); }
  			public int [] nextInts () {
  				String [] S = nextStrings(); int N = S.length;
  				int [] res = new int [N];
  				for (int i = 0; i < N; ++i)
  					res[i] = Integer.parseInt(S[i]);
  				return res;
  			}
  			public int [][] nextInts (int N) {
  				int [][] res = new int [N][];
  				for (int i = 0; i < N; ++i)
  					res[i] = nextInts();
  				return res;
  			}
  			//////////////////////////////////////////////
  			private boolean eol () { return index == line.length; }
  			private String readLine () {
  				try {
  					int b;
  					StringBuilder res = new StringBuilder();
  					while ((b = System.in.read()) < ' ')
  						continue;
  					res.append((char)b);
  					while ((b = System.in.read()) >= ' ')
  						res.append((char)b);
  					return res.toString();
  				} catch (Exception e) {
  					throw new Error (e);
  				}
  			}
  			private MyScanner () {
  				try {
  					while (System.in.available() == 0)
  						Thread.sleep(1);
  					start();
  				} catch (Exception e) {
  					throw new Error(e);
  				}
  			}
  			private String [] line;
  			private int index;
  			private void newLine () {
  				if (line == null || eol()) {
  					line = split(readLine());
  					index = 0;
  				}
  			}
  			private String [] split (String s) { return s.length() > 0 ? s.split(" ") : new String [0]; }
  		}
  		private static String build (Object o, Object ... A) { return buildDelim(" ", o, A); }
  		private static String buildDelim (String delim, Object o, Object ... A) {
  			java.util.List<String> str = new java.util.ArrayList<>();
  			append(str, o);
  			for (Object p : A)
  				append(str, p);
  			return String.join(delim, str.toArray(new String [0]));
  		}
  		//////////////////////////////////////////////////////////////////////////////////
  		private static java.text.DecimalFormat formatter = new java.text.DecimalFormat("#.#########");
  		private static void start () { if (t == 0) t = millis(); }
  		private static void append (java.util.function.Consumer<Object> f, java.util.function.Consumer<Object> g, Object o) {
  			if (o.getClass().isArray()) {
  				int len = java.lang.reflect.Array.getLength(o);
  				for (int i = 0; i < len; ++i)
  					f.accept(java.lang.reflect.Array.get(o, i));
  			}
  			else if (o instanceof Iterable<?>)
  				((Iterable<?>)o).forEach(f::accept);
  			else
  				g.accept(o instanceof Double ? formatter.format(o) : o);
  		}
  		private static void append (java.util.List<String> str, Object o) {
  			append(x -> append(str, x), x -> str.add(x.toString()), o);
  		}
  		private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out);
  		private static void flush () { pw.flush(); System.out.flush(); }
  		private static void print (Object o, Object ... A) {
  			String res = build(o, A);
  			if (DEBUG == 2)
  				err(res, '(', time(), ')');
  			if (res.length() > 0)
  				pw.println(res);
  			if (DEBUG == 1)
  				flush();
  		}
  		private static void err (Object o, Object ... A) { System.err.println(build(o, A)); }
  		private static int DEBUG;
  		private static void exit () {
  			String end = "------------------" + System.lineSeparator() + time();
  			switch(DEBUG) {
  			case 1: print(end); break;
  			case 2: err(end); break;
  			}
  			IOUtils.pw.close();
  			System.out.flush();
  			System.exit(0);
  		}
  		private static long t;
  		private static long millis () { return System.currentTimeMillis(); }
  		private static String time () { return "Time: " + (millis() - t) / 1000.0; }
  		private static void run (int N) {
  			try { DEBUG = Integer.parseInt(System.getProperties().get("DEBUG").toString()); }
  			catch (Throwable t) {}
  
  			for (int n = 1; n <= N; ++n) {
  				Object res = new E().solve();
  				if (res != null) {
  					@SuppressWarnings("all")
  					Object o = CONTEST_TYPE == 0 ? "Case #" + n + ": " + build(res) : res;
  					print(o);
  				}
  			}
  			exit();
  		}
  	}
  	////////////////////////////////////////////////////////////////////////////////////
  	public static void main (String[] args) {
  		@SuppressWarnings("all")
  		int N = CONTEST_TYPE == 1 ? 1 : sc.nextInt();
  		init();
  		IOUtils.run(N);
  	}
  }
  