#include <bits/stdc++.h>
using namespace std;
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
// #define ordered_set tree<int, null_type,less_equal<int>, rb_tree_tag,tree_order_statistics_node_update>
#define int long long int
#define endl "\n"
#define MOD 1000000007
#define mod 1000000007
#define M 1000000007
#define pb push_back
#define take(a,b,c) for(int b=0;b<c;b++) cin>>a[b]
#define boost ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define mx 1000005
#define fiint(a,b) memset(a,b,sizeof(a))
#define bitcount __builtin_popcount
#define fori(i,a,b) for(int i=a;i<b;i++)
#define ford(i,a,b) for(int i=a;i>=b;i--)
#define debug(x) cout<<x<<endl;
#define cases(t) int t; cin>>t; while(t--)
#define inf1 INT_MAX
#define all(a) a.begin(),a.end()
#define vec vector<int>
#define pii pair<int,int>
#define plii pair<int,int>
#define pint pair<int,int>
#define ff first
#define ss second
#define lb lower_bound
#define ub upper_bound
#define bs binary_search
#define mp make_pair
 
#define sz(x) (int)x.size()
#define PI    3.14159265359

//const long long INF=1e18;

bool chmin(int& a, int b){ if(a > b){ a = b; return 1; } return 0; }

 
int factorial[10000001]={0};
 
int gcd(int a, int b){
    if (b == 0)
        return a;
    return gcd(b, a % b);
}


int powerFunction(int x,int y){
    int res = 1;
     int p = mod;
    x = x;
    while (y > 0){
        if (y & 1)
            res = (res*x)%p ;
        y = y>>1;
        x = (x*x)%p ;
    }
    return res;
}

void factorialFunction(int maxLimit){
    factorial[0]=1;
    for(int i=1 ; i <= maxLimit ; i++)
    factorial[i]=(factorial[i-1]*i)%MOD;
    return;
}
 
int nCr(int n, int r)
{
    if(r < 0 || r > n){
        return 0;
    }
    int temp = factorial[n];
    temp *= (powerFunction(factorial[r], MOD-2)%MOD);
    temp %= MOD;
    temp *= (powerFunction(factorial[n-r], MOD-2)%MOD);
    temp %= MOD;
    return temp;
}

vec p(300005);
vec si(300005);
//vec di
vector<map<int,int>> cnt(300005);
int find_p(int a)
{
    while(p[a] != a)
    {
        //int le = si[p[a]];
        p[a] = p[p[a]];
        //si[p[a]] += le;
        a = p[a];
        
    }
    return a;
}

void merge(int a , int b)
{
     a = find_p(a);
     b = find_p(b);
    if(a == b)
        return;
    if(si[a] >= si[b])
    {
        si[a] += si[b];
        p[b] = a;
        for(auto it : cnt[b])
            cnt[a][it.ff] += it.ss;
    }
    else
    {
        si[b] += si[a];
        p[a] = b;
        for(auto it : cnt[a])
            cnt[b][it.ff] += it.ss;
    }
}

signed main()
{
    int n,q;cin>>n>>q;
   
    for(int i = 0 ; i < n ;i++)
    {
        int a ; cin>>a; a--; cnt[i][a] = 1;
        p[i] = i;
        si[i] = 1;
    }
    while(q--)
    {
        int t , x , y ; cin >>t >> x >> y;
        x-- ; y--;
        if(t == 1 )
        {
            merge(x , y);
        }
        else
        {
            cout<<cnt[find_p(x)][y]<<endl;
        }
    }
    
}
    



#include <iostream>
#include <vector>
#include <map>
using namespace std;

struct uf_tree {
    std::vector<int> parent;
    std::vector<std::map<int, int>> dict;
    int __size;
    uf_tree(int size_) : parent(size_, -1), dict(size_), __size(size_) {}
    void unite(int x, int y) {
        if ((x = find(x)) != (y = find(y))) {
            if (parent[y] < parent[x]) std::swap(x, y);
            parent[x] += parent[y];
            parent[y] = x;
            for (auto [key, val] : dict[y]) {
                dict[x][key] += val;
            }
            __size--;
        }
    }
    bool is_same(int x, int y) { return find(x) == find(y); }
    int find(int x) { return parent[x] < 0 ? x : parent[x] = find(parent[x]); }
    int size(int x) { return -parent[find(x)]; }
    int size() { return __size; }
    int query(int x, int y) { return dict[find(x)][y]; }
};

int main() {
    int n, q;
    cin >> n >> q;
    vector<int> cs(n);
    uf_tree uf(n);
    for (int i = 0; i < n; i++) {
        cin >> cs[i];
        uf.dict[i][cs[i]]++;
    }
    for (int i = 0; i < q; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        if (a == 1) {
            uf.unite(b -1, c - 1);
        } else {
            cout << uf.query(b - 1, c) << endl;
        }
    }
    return 0;
}