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

#define REP(i,n) for(int i=0;i<(n);i++)
#define ALL(v) v.begin(),v.end()

struct UnionFind{
  int num;//連結成分の数
  vector<int> r,p;//そのグループのサイズ,自分の親っぽいやつ
  vector<map<int,int>> mp;
  UnionFind(){}
  UnionFind(int n):num(n),r(n,1),mp(n),p(n,0){iota(p.begin(),p.end(),0);}

  int find(int x){//どのグループに所属するか
    return (x==p[x]?x:p[x]=find(p[x]));//xがグループの名前と一致するまでxを親にする
  }

  bool same(int x,int y){//同じグループかどうか
    return find(x)==find(y);
  }

  void unite(int x,int y){//xとyを同じグループにする
    x=find(x);y=find(y);//xとyのグループの名前をどっちかが変える
    if(x==y) return;
    if(mp[x].size()<mp[y].size()) swap(x,y);//サイズが大きい方をxとする
    for(auto p:mp[y])mp[x][p.first]+=p.second;
    p[y]=x;
    num--;
  }

  int size(int x){//グループの大きさ
    return r[find(x)];
  }

  int count() const{//グループの数
    return num;
  }
};

signed main(){
  int n,q;cin>>n>>q;
  UnionFind uf(n);
  REP(i,n){
    int c;cin>>c;c--;uf.mp[i][c]++;
  }
  REP(_,q){
    int c,a,b;cin>>c>>a>>b;a--;b--;
    if(c==1)uf.unite(a,b);
    else cout<<uf.mp[uf.find(a)][b]<<endl;
  }
}

#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
using iPair = pair<int,int>;
using lPair = pair<ll, ll>;
using ivector = vector<int>;
using lvector = vector<ll>;
using istack = stack<int>;
using iqueue = queue<int>;
using ivv = vector<vector<int>>;
using lvv = vector<vector<ll>>;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
vector<iPair> dir = {{1,0}, {-1,0}, {0,1}, {0,-1}};
#define dump(x) cout << #x << " = " << (x) << endl
#define ALL(x) begin(x),end(x)
#define rep(i,s,e) for(ll i=(s), i_stop=(e); i<i_stop; ++i)
#define repRev(i,s,e) for(ll i=(e)-1, i_stop=(s); i>=i_stop; --i)
#define range(i,s,n) for(ll i=(s), i_stop=(s)+(n); i<i_stop; ++i)
#define rangeRev(i,s,n) for(ll i=(s), i_stop=(s)-(n); i>i_stop; --i)
#define foreach(x,container) for(auto &&x:container)
bool chmax(ll& a, ll b) {if(a<b) {a=b;return true;} return false;}
bool chmin(ll& a, ll b) {if(a>b) {a=b;return true;} return false;}
template<typename T> void printArr(vector<T> &arr){
    for(auto &&x:arr) {cout << x << " ";} cout << endl;
}


/*


## 關鍵詞：

## 題意：


## 思路：

## 雜多：


*/

#define maxn 200000
int r[maxn+10];
int father[maxn+10];
map<int,int> group[maxn+10];

int find_top(int x) {
    if(father[x] == x) return x;
    else return (father[x] = find_top(father[x]));
}

void merge(int x, int y) {
    int fax = find_top(x);
    int fay = find_top(y);
    if(fax == fay) return;
    if(r[fax] < r[fay]) {
        father[fax] = fay;
        r[fay] += r[fax];
        for(auto&& [k,v]: group[fax]) {
            group[fay][k] += v;
        }
    }else{
        father[fay] = fax;
        r[fax] += r[fay];
        for(auto&& [k,v]: group[fay]) {
            group[fax][k] += v;
        }
    }
}

void solve() {
    // 預處理
    range(i, 1, maxn) {father[i] = i; r[i] = 1;}

    int n,q; cin>>n>>q;
    range(i, 1, n) {
        int c; cin>>c;
        group[i][c] = 1;
    }

    while(q--) {
        int op, x, y; cin>>op>>x>>y;
        if(op == 1) {
            merge(x, y);
        }else{
            cout << group[find_top(x)][y] << endl;
        }
    }
}


int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    solve();
    return 0;
}

    
    