#include <bits/stdc++.h>
using namespace std;

const int MN = 200012;

int n, q;
int c[MN];
int id[MN];
set<int> st[MN];
map<int, int> ctr[MN];

int main (void) {
  ios::sync_with_stdio(false);cin.tie(0);
  cin >> n >> q;
  for (int i = 1; i <= n; i++) {
    cin >> c[i];
    id[i] = i;
    st[i].insert(i);
    ctr[i][c[i]] = 1;
  }
  while (q--) {
    int op, x, y;
    cin >> op >> x >> y;
    if (op == 1) {
      if (id[x] == id[y]) continue;
      set<int>& sa = st[id[x]];
      set<int>& sb = st[id[y]];
      map<int, int>& ma = ctr[id[x]];
      map<int, int>& mb = ctr[id[y]];
      if (sa.size() < sb.size()) {
        for (int s : sa) {
          id[s] = id[y];
          sb.insert(s);
          mb[c[s]]++;
        }
        sa.clear();
        ma.clear();
      } else {
        for (int s : sb) {
          id[s] = id[x];
          sa.insert(s);
          ma[c[s]]++;
        }
        sb.clear();
        mb.clear();
      }
    } else {
      cout << ctr[id[x]][y] << '\n';
    }
  }
  return 0;
}


#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <functional>
#include <cassert>
#include <iomanip>
#include <numeric>
#include <memory>
#include <random>
#define vll vector<ll>
#define vvvl vector<vvl>
#define vvl vector<vector<ll>>
#define VV(a, b, c, d) vector<vector<d>>(a, vector<d>(b, c))
#define VVV(a, b, c, d) vector<vvl>(a, vvl(b, vll (c, d)));
#define re(c, b) for(ll c=0;c<b;c++)
#define all(obj) (obj).begin(), (obj).end()
typedef long long int ll;
typedef long double ld;
using namespace std;


template<typename Key, typename Cnt=int>
struct hashmultiset{
  float load_factor = 0.8;
  int table_size = 16;
  int mod = 15;
  const Key null_key;
  uint32_t mask;
  Cnt valid_size;
  int valid_type;
  vector<int> idx_table;
  vector<pair<Key, Cnt>> data;
  function<uint32_t(Key)> f = std::hash<uint32_t>();

  void expand_table(){
    table_size *= 2;
    mod = table_size - 1;
    idx_table.resize(table_size);
    fill(idx_table.begin(), idx_table.end(), -1);
    for(int i=0;i<data.size();i++){
      if(data[i].first==null_key) continue;
      inner_insert(i);
    }
  }
  void inner_insert(int idx){
    uint32_t h = f(data[idx].first^mask) & mod;
    while(true){
      if(idx_table[h]==-1){
        idx_table[h] = idx;
        return;
      }
      h = (h + 1) & mod;
    }
  }
public:
  hashmultiset():
    null_key(std::numeric_limits<Key>::max()),mask(random_device()()),
    valid_size(0), valid_type(0), idx_table(table_size, -1){}

  //データの数の総和
  Cnt size(){
    return valid_size;
  }
  //データの種類数
  int type(){
    return valid_type;
  }
  //kをx個数入れる
  void insert(Key k, Cnt x=1){
    assert(k!=null_key);
    uint32_t h = f(k^mask) & mod;
    while(true){
      int idx = idx_table[h];
      if(idx!=-1){
        if(data[idx].first==k){
          data[idx].second += x;
          valid_size += x;
          return;
        }
        h = (h + 1) & mod;
      }else{
        data.push_back({k, x});
        idx_table[h] = int(data.size()) - 1;
        valid_size += x;
        valid_type++;
        if(float(data.size())>load_factor*float(table_size)){
          expand_table();
        }
        return;
      }
    }
  }
  //kを最大x個消す(0未満にはならない。inf個消すこととstd::multisetのeraseは同じ挙動)
  void erase(Key k, Cnt x=std::numeric_limits<Cnt>::max()){
    assert(k!=null_key);
    uint32_t h = f(k^mask) & mod;
    while(true){
      int idx = idx_table[h];
      if(idx==-1) return;
      if(data[idx].first==k){
        if(data[idx].second > x) {
          data[idx].second -= x;
          valid_size -= x;
        }else {
          data[idx].first = null_key;
          valid_size -= data[idx].second;
          valid_type--;
        }
        return;
      }
      h = (h + 1) & mod;
    }
  }
  //kの個数
  int count(Key k){
    assert(k!=null_key);
    uint32_t h = f(k^mask) & mod;
    while(true){
      int idx = idx_table[h];
      if(idx==-1) return 0;
      if(data[idx].first==k) return data[idx].second;
      h = (h + 1) & mod;
    }
  }
};
vector<int> par(200001);

int find(int x){
  if(par[x]==x) return x;
  return par[x] = find(par[x]);
}

int main(){
  int n, q;scanf("%d %d", &n, &q);
  for(int i=0;i<n;i++) par[i] = i;
  vector<hashmultiset<int>> hs(n);

  for(int i=0;i<n;i++){
    int c;scanf("%d", &c);
    hs[i].insert(c, 1);
  }

  for(int i=0;i<q;i++){
    int a, b, c;scanf("%d %d %d", &a, &b, &c);
    if(a==1){
      b = find(b-1);
      c = find(c-1);
      if(b==c) continue;
      if(hs[b].type()>hs[c].type()) swap(b, c);
      //b to c
      for(auto e:hs[b].data){
        if(e.first==hs[b].null_key) continue;
        hs[c].insert(e.first, e.second);
      }
      par[b] = c;
    }else{
      b = find(b-1);
      printf("%d\n", hs[b].count(c));
    }
  }
}
