#include<bits/stdc++.h>
using namespace std;
#define vi vector<int>
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define pi 3.141592653589793238
#define rep(i,a,b) for (int i = a; i <= b; i++)
#define zip(i,a,b) for(int i=a;i<b;i++)
#define rzip(i,a,b) for(int i=a;i>=b;i--)
#define ll unsigned int
#define test int t;cin>>t; while(t--)
#define en '\n'
typedef pair<int, int>     pii;
typedef pair<char, int>    pci;
typedef pair<char, char>   pcc;
typedef vector<pii>       vii;
typedef long double ld;
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(),v.rend()
#define sz(x) (int)x.size()
#define INF (1e18+5)
#define inf (1e9+5)
#define mod 1000000007


void __print(int x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}
// You should only debug a pair of simple data types. For example,
// the debug won't work if one of pair's elements is collection type
// (std::vector, std::map, std::set...).
template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i : x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif


// bool check_prime(int n)  return whether a number is prime or not O(sqrt(N));
// int BE(int x,int n,int m)  return x^n%m; O(logN);
// void sieve()  from number 1-1000001 saare prime store kar lega  in bool is_prime[1000001] array
// vector<int> z_array(string s)  return vector which is Z-array of string s;
// vector<int> lps(string s)      return vector which is lps array of string s;
// int power(int x,int n) return x^n; O(logN);
// using_ordered_set (template for using ordered set , replace first 2 lines of this page with this code..);
const int gf = 1e6 + 9;

vi v[gf];
int sze[gf], parent[gf];
map<int, int>m1[gf];

void make_set(int v) {
	parent[v] = v;
	sze[v] = 1;
}

int find_set(int v) {
	if (v == parent[v])
		return v;
	return parent[v] = find_set(parent[v]);
}


void union_set(int a, int b) {
	a = find_set(a);
	b = find_set(b);
	if (a != b) {
		if (sze[a] < sze[b])
			swap(a, b);
		parent[b] = a;
		sze[a] += sze[b];
		for (auto it : m1[b])
		{
			m1[a][it.ff] += m1[b][it.ff];
		}
	}
}

int32_t main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(0);
#ifndef ONLINE_JUDGE
	if (fopen("input.txt", "r"))
	{
		freopen ("input.txt" , "r" , stdin);
		freopen ("output.txt" , "w" , stdout);
	}
#endif
	//_______________________________-code starts-_______________________________________________
	int n, q;
	cin >> n >> q;
	rep(i, 1, n) {
		make_set(i);
	}
	int c[n + 1];
	rep(i, 1, n)
	{
		cin >> c[i];
		m1[parent[i]][c[i]]++;
		v[c[i]].pb(i);
	}
	vi vec;
	zip(i, 0, q)
	{
		int lol;
		cin >> lol;
		if (lol == 1)
		{
			int a, b;
			cin >> a >> b;
			if (find_set(a) != find_set(b))
			{
				union_set(a, b);
			}
		}
		else
		{
			int x, y;
			cin >> x >> y;
			cout << m1[find_set(x)][y] << en;
		}
	}

	return 0;
}



#include<bits/stdc++.h>

#define vi             vector<int>
#define vb             vector<bool>
#define vs             vector<string>
#define vvi            vector<vector<int>>
#define vpi            vector<pair<int,int>>
#define pb             push_back
#define mp             make_pair
#define int            long long int
#define mod            1000000007
#define from(i,n)      for(int i=0;i<(int)n;i++)
#define from_j(i,j,n)  for(int i=j;i<(int)n;i++)
using namespace std;

int power(int n , int k) {
    if (k == 0)return 1;
    int temp = power(n, k / 2);
    temp = (temp * temp);
    if (k % 2) return (temp * n);
    return temp;
}
int fact(int x)
{
    int res = 1;
    for(int i=2;i<=x;i++)
        res = i*res;
    return res;
}

int choose(int n, int r)
{
    return fact(n)/(fact(r)*fact(n-r));
}

int gcd(int a, int b)
{
    if (min(a, b) == 0)
        return max(a, b);
    return gcd(min(a, b), max(a, b) % min(a, b));
}
 
int lcm(int a, int b)
{
    int x = gcd(a, b);
    return abs(a*b) / x;
}

void sync()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
/*
  #ifndef ONLINEJUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    freopen("error.txt", "w", stderr);
    #endif
*/
}

int32_t main() {
    sync();
    
    int n, k;
    cin>>n>>k;
    vvi T(n, vi (n));
    from(i,n) 
    	from(j,n)
    		cin>>T[i][j];
    vi idx;
    from(i,n)
    	idx.pb(i);

   	int ans = 0;
    do
    {
    
    	int t = 0;
    	from(i,n)
    	{
    		t += T[idx[i]][idx[(i+1)%n]];
    	}
    	if(t == k)
    			ans++;

    }
    while(next_permutation(idx.begin()+1,idx.end()));
    
    cout<<ans;


    cerr << "Time : " << 1000 * ((double)clock()) / (double)CLOCKS_PER_SEC << "ms\n"; 
	return 0;   
} 
