#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstring>
#include <iostream>
#include <sstream>
#include <numeric>
#include <map>
#include <set>
#include <queue>
#include <vector>

using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<LL, LL> II;
typedef pair<LL, II> III;

static const LL INF = 1LL << 60;
static const long long MOD = 998244353;
static const size_t MAX_N = 1000001;

struct modll {
	long long x;
	modll() { }
	modll(int _x) : x(_x) { }
	operator int() const { return (int)x; }
	modll operator+(int y) { return (x + y + MOD) % MOD; }
	modll operator+=(int y) { x = (x + y + MOD) % MOD; return *this; }
	modll operator-(int y) { return (x - y + MOD) % MOD; }
	modll operator-=(int y) { x = (x - y + MOD) % MOD; return *this; }
	modll operator*(int y) { return (x * y) % MOD; }
	modll operator*=(int y) { x = (x * y) % MOD; return *this; }
	modll operator/(int y) { return (x * modpow(y, MOD - 2)) % MOD; }
	modll operator/=(int y) { x = (x * modpow(y, MOD - 2)) % MOD; return *this; }
	static modll modinv(int a) { return modpow(a, MOD - 2); }
	static modll modpow(int a, int b) {
		modll x = a, r = 1;
		for (; b; b >>= 1, x *= x) if (b & 1) r *= x;
		return r;
	}
};

modll combination(LL n, LL r) {
	static modll fact[MAX_N + 1], inv[MAX_N + 1];
	if (!fact[0]) {
		fact[0] = 1;
		for (int i = 1; i <= MAX_N; ++i) {
			fact[i] = fact[i - 1] * i;
		}
		inv[MAX_N] = modll::modinv(fact[MAX_N]);
		for (int i = MAX_N; i >= 1; --i) {
			inv[i - 1] = inv[i] * i;
		}
	}
	if (r > n) {
		return 0;
	}
	return (fact[n] * inv[r]) * inv[n - r];
}

LL solve(long long H, long long W, std::vector<std::string> &S) {
	modll ans = 1;
	for (int i = 0; i < H + W; ++i) {
		int ac = 0, rc = 0, bc = 0;
		for (int c = 0; c < W; ++c) {
			int r = i - c;
			if (r >= 0 && r < H) {
				++ac;
				if (S[r][c] == 'R') ++rc;
				if (S[r][c] == 'B') ++bc;
			}
		}
		if (ac) {
			if (rc && bc) {
				return 0;
			}
			if (rc == 0 && bc == 0) {
				ans *= 2;
			}
		}
	}
	return ans;
}

int main() {
    long long H, W;
	std::cin >> H >> W;
	std::vector<std::string> S(H);
	for (int i = 0; i < H; i++) {
		std::cin >> S[i];
	}
	cout << solve(H, W, S) << endl;
	return 0;
}

#line 1 "main.cpp"

/**
 * @title Template
 */

#include <iostream>
#include <algorithm>
#include <utility>
#include <numeric>
#include <vector>
#include <array>
#include <cassert>
#include <map>

#line 2 "/Users/kodamankod/Desktop/cpp_programming/Library/other/chmin_chmax.cpp"

template <class T, class U>
constexpr bool chmin(T &lhs, const U &rhs) {
  if (lhs > rhs) { lhs = rhs; return true; }
  return false;
}

template <class T, class U>
constexpr bool chmax(T &lhs, const U &rhs) {
  if (lhs < rhs) { lhs = rhs; return true; }
  return false;
}

/**
 * @title Chmin/Chmax
 */
#line 2 "/Users/kodamankod/Desktop/cpp_programming/Library/other/range.cpp"

#line 4 "/Users/kodamankod/Desktop/cpp_programming/Library/other/range.cpp"

class range {
  struct iter {
    std::size_t itr;
    constexpr iter(std::size_t pos) noexcept: itr(pos) { }
    constexpr void operator ++ () noexcept { ++itr; }
    constexpr bool operator != (iter other) const noexcept { return itr != other.itr; }
    constexpr std::size_t operator * () const noexcept { return itr; }
  };

  struct reviter {
    std::size_t itr;
    constexpr reviter(std::size_t pos) noexcept: itr(pos) { }
    constexpr void operator ++ () noexcept { --itr; }
    constexpr bool operator != (reviter other) const noexcept { return itr != other.itr; }
    constexpr std::size_t operator * () const noexcept { return itr; }
  };

  const iter first, last;

public:
  constexpr range(std::size_t first, std::size_t last) noexcept: first(first), last(std::max(first, last)) { }
  constexpr iter begin() const noexcept { return first; }
  constexpr iter end() const noexcept { return last; }
  constexpr reviter rbegin() const noexcept { return reviter(*last - 1); } 
  constexpr reviter rend() const noexcept { return reviter(*first - 1); } 
};

/**
 * @title Range
 */
#line 17 "main.cpp"

using i32 = std::int32_t;
using i64 = std::int64_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;

constexpr i32 inf32 = (i32(1) << 30) - 1;
constexpr i64 inf64 = (i64(1) << 62) - 1;

usize find(std::vector<usize> &vec, usize x) {
  if (vec[x] == x) {
    return x;
  }
  return vec[x] = find(vec, vec[x]);
}

int main() {
  usize N, Q;
  std::cin >> N >> Q;
  std::vector<std::map<usize, usize>> map(N);
  for (auto i: range(0, N)) {
    usize c;
    std::cin >> c;
    c -= 1;
    map[i][c] += 1;
  }
  std::vector<usize> par(N);
  for (auto i: range(0, N)) {
    par[i] = i;
  }
  while (Q--) {
    usize t;
    std::cin >> t;
    if (t == 1) {
      usize a, b;
      std::cin >> a >> b;
      a -= 1;
      b -= 1;
      a = find(par, a);
      b = find(par, b);
      if (a != b) {
        if (map[a].size() < map[b].size()) {
          std::swap(a, b);
        }
        for (auto [x, y]: std::move(map[b])) {
          map[a][x] += y;
        }
        par[b] = a;
      }
    }
    else {
      usize a, b;
      std::cin >> a >> b;
      a -= 1;
      b -= 1;
      a = find(par, a);
      auto itr = map[a].find(b);
      if (itr != map[a].end()) {
        std::cout << itr -> second << '\n';
      }
      else {
        std::cout << "0\n";
      }
    }
  }
  return 0;
}
