#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mit map<int,int>::iterator
#define sit set<int>::iterator
#define itrm(g,x) for(mit g=x.begin();g!=x.end();g++)
#define itrs(g,x) for(sit g=x.begin();g!=x.end();g++)
#define ltype int
#define rep(i,j,k) for(ltype(i)=(j);(i)<=(k);(i)++)
#define rap(i,j,k) for(ltype(i)=(j);(i)<(k);(i)++)
#define per(i,j,k) for(ltype(i)=(j);(i)>=(k);(i)--)
#define pii pair<int,int>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back
#define fastio ios::sync_with_stdio(false)
#define check(x) if(x>=mod) x-=mod
const int inf=0x3f3f3f3f,mod=998244353;
const double pi=3.1415926535897932,eps=1e-6;
void chmax(int &x,int y){if(x < y) x = y;}
void chmin(int &x,int y){if(x > y) x = y;}
int qpow(int x,int y){
    int ret = 1;
    while(y) {
        if(y & 1) ret = (ll)ret * x % mod;
        x = (ll)x * x % mod;
        y >>= 1;
    }
    return ret;
}
template<int md> struct modint{
    int x;
    modint(int v = 0) {x = v; if(x >= md || x < 0) {x %= md; if(x < 0) x += md;}}
    operator int() const {return x;}
    friend modint operator +=(modint &a,const modint &b) {
        a.x += b.x;
        if(a.x >= md) a.x -= md;return a;
    }
    friend modint operator +(modint a,const modint &b) {
        return a += b;
    }
    friend modint operator -=(modint &a,const modint &b) {
        a.x -= b.x;a.x += md;
        if(a.x >= md) a.x -= md;return a;
    }
    friend modint operator -(modint a,const modint &b) {
        return a -= b;
    }
    friend modint operator *=(modint &a,const modint &b) {
        a.x = (ll)b.x * a.x % md;
        return a;
    }
    friend modint operator *(modint a,const modint &b) {
        return a *= b;
    }
    friend modint operator *(modint a,int b) {
        return a *= modint(b);
    }
    friend modint operator /=(modint &a,const modint &b) {
        a.x = (ll)b.x * qpow(a.x, md - 2) % md;
        return a;
    }
    friend modint operator /(modint a,const modint &b) {
        return a /= b;
    }
    friend modint operator /(modint a,int b) {
        return a /= modint(b);
    }
    friend modint operator ^(modint a,int b) {
        return qpow(a.x, b);
    }
};
int n,m,k,a[5005][5005],pre[5005][5005];modint<998244353> dp[5005][5005][3],pw[5005];
char s[5];
int main()
{
    pw[0] = 1;
    rep(i,1,5000) pw[i] = pw[i - 1] * 3;
    scanf("%d%d%d",&n,&m,&k);
    rep(i,1,k) {
        int x,y;
        scanf("%d%d%s",&x,&y,s);
        if(s[0] == 'X') a[x][y] = 1;
        if(s[0] == 'R') a[x][y] = 3;
        if(s[0] == 'D') a[x][y] = 2;
    }
    rep(i,1,n) {
        rep(j,1,m) pre[i][j] = pre[i][j-1] + (a[i][j] == 0);
    }
    dp[1][1][0] = dp[1][1][1] = dp[1][1][2] = 1;
    rep(i,1,n) rep(j,1,m) {
        int u = a[i][j] - 1;
        if(u == 0) dp[i][j][1] = dp[i][j][2] = 0;
        if(u == 1) dp[i][j][0] = dp[i][j][2] = 0;
        if(u == 2) dp[i][j][0] = dp[i][j][1] = 0;
        dp[i+1][j][0] += (dp[i][j][0] + dp[i][j][1]) * pw[pre[i][m] - pre[i][j] + pre[i + 1][j - 1]];
        dp[i+1][j][1] = dp[i+1][j][2] = dp[i+1][j][0];
        dp[i][j+1][0] += dp[i][j][0] + dp[i][j][2];
        dp[i][j+1][1] = dp[i][j+1][2] = dp[i][j+1][0];
        //printf("%d %d %d %d %d\n",i,j,dp[i][j][0],dp[i][j][1],dp[i][j][2]);
    }
    modint<998244353> ans = dp[n][m][0] + dp[n][m][1] + dp[n][m][2];
    printf("%d\n",ans.x);
    return 0;
}
#include <iostream>
#include <complex>
#include <vector>
#include <string>
#include <algorithm>
#include <cstdio>
#include <numeric>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <cmath>
#include <bitset>
#include <cassert>
#include <queue>
#include <stack>
#include <deque>
#include <random>
#include <iomanip>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
typedef long long int ll;
typedef long double ld;
typedef pair<ll,ll> P;
const ll MOD=1000000007;
const ll MAX_N=500010;
const ll INF=999999999999;

struct union_find {
	ll par[MAX_N];
	ll Size[MAX_N];
	union_find(ll n) {
		for (int i = 0; i < n; i++) {
			par[i] = i;
			Size[i] = 1;
		}
	}
	ll root(ll x) {
		if (par[x] == x)return x;
		return par[x] = root(par[x]);
	}
	bool same(ll x, ll y) {
		return root(x) == root(y);
	}
	void unite(ll x, ll y) {
		if (same(x, y))return;
		Size[root(x)] += Size[root(y)];
		par[root(y)] = root(x);
	}
};

int main(){
    int n,q;
    cin>>n>>q;
    vector<int> c(n);
    vector<int> ans(0);
    vector<map<int,int> > mps(n);
    struct union_find U(n);

    for(int i=0;i<n;i++){
        cin>>c[i];
        c[i]--;
        mps[i][c[i]]=1;
    }

    while(q){
        q--;
        int type;
        cin>>type;
        if(type==1){
            int a,b;
            cin>>a>>b;
            a--; b--;
            if(U.same(a,b)) continue;
            if(U.Size[U.root(a)] > U.Size[U.root(b)]){
                for(auto p : mps[U.root(b)]){
                    mps[U.root(a)][p.first] += p.second;
                }
                U.unite(a,b);
            }else{
                for(auto p : mps[U.root(a)]){
                    mps[U.root(b)][p.first] += p.second;
                }
                U.unite(b,a);
            }
        }else{
            int x,y;
            cin>>x>>y;
            x--; y--;
            ans.push_back(mps[U.root(x)][y]);
        }
    }
    for(int a:ans) cout<<a<<endl;
}