#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define REP(i,n) for (int i = 1; i < (int)(n); i++)
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
#define debug(var) do{cout << #var << " : "; view(var);}while(0)
template<class T> bool chmin(T &a, T b) {if(a>b) {a=b;return 1;}return 0;}
template<class T> bool chmax(T &a, T b) {if(a<b) {a=b;return 1;}return 0;}
using namespace std;
template<class T> void view(T e) {cout << e << endl;}
template<class T> void view(const vector<T> &v) {for(const auto &e : v){cout << e << " ";} cout << endl;}
template<class T> void view(const vector<vector<T>> &vv) {for(const auto &v : vv){view(v);}}
using vint = vector<int>;
using vvint = vector<vector<int>>;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using P = pair<int,int>;
const int inf = 1<<30;
const ll inf_l = 1LL<<61;
const int MAX = 1e5;

// union-find
struct union_find {
    vector<int> dat;

    union_find(int size) {dat.resize(size,-1);}

    int find(int x) {
        if (dat[x] < 0) {return x;}
        return dat[x] = find(dat[x]);
    }

    bool unite(int x, int y) {
        x = find(x); y = find(y);
        if (x == y) {return false;}
        if (dat[x] > dat[y]) swap(x,y);
        dat[x] += dat[y];
        dat[y] = x;
        return true;
    }

    int size(int x) {return -dat[find(x)];}
};

int main() {
    int n, q; cin >> n >> q;
    vector<map<int,int>> ct(n);
    rep(i,n) {
        int c; cin >> c;
        ct[i][c]++;
    }
    union_find uf(n);
    rep(i,q) {
        int query, a, b; cin >> query >> a >> b;
        if (query == 1) {
            a--; b--;
            a = uf.find(a);
            b = uf.find(b);
            if (uf.unite(a, b)) {
                int r = uf.find(a);
                for (P p : ct[a + b - r]) {
                    ct[r][p.first] += p.second;
                }
            }
        } else {
            a--;
            cout << ct[uf.find(a)][b] << endl;
        }
    }
}
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define pb push_back

// g++ -std=c++17 -Wshadow -Wall -g -fsanitize=address -fsanitize=undefined -D_GLIBCXX_DEBUG -o 

const int nax=2e5+5;
int par[nax],sz[nax];
map<int,int>adj[nax];
int get(int a){
 return (par[a]==a)?a:get(par[a]);
}
void Union(int a,int b){
 a=get(a);
 b=get(b);
 if(a==b)return;
 if(sz[a]<sz[b])swap(a,b);
 par[b]=a;
 sz[a]+=sz[b];
 for(auto x:adj[b]){
  adj[a][x.first]+=x.second;
 }
}
int n,q;
int c[nax];
int main(){
 cin>>n>>q;
 for(int i=1;i<=n;i++){
  cin>>c[i];
  sz[i]=1;
  par[i]=i;
  adj[i][c[i]]++;
 }
 for(int i=0;i<q;i++){
  int ch,a,b;
  cin>>ch>>a>>b;
  if(ch==1)Union(a,b);
  else{
   a=get(a);
   cout<<adj[a][b]<<"\n";
  }
 }
 return 0;
}
