#include <bits/stdc++.h>
using namespace std;
const int maxl=300005,LG=55;

int n,m,q,num=0,opt,u,v;
int a[maxl],tree[maxl*LG],L[maxl*LG],R[maxl*LG];
int fa[maxl],RT[maxl];

int fin(int x)
{
	if (x==fa[x])  return x;
	return fa[x]=fin(fa[x]);
}

void pushup(int rt)
{
	tree[rt]=tree[L[rt]]+tree[R[rt]];
}

int change(int nl,int l,int r,int rt,int k)
{
	if (rt==0)  rt=++num;
	if (l==r)
	{
		tree[rt]+=k;
		return rt;
	}
	int mid=(l+r)>>1;
	if (nl<=mid)  L[rt]=change(nl,l,mid,L[rt],k);
	else R[rt]=change(nl,mid+1,r,R[rt],k);
	
	pushup(rt);

	return rt;
}

int query(int nl,int l,int r,int rt)
{
	if (l==r)  return tree[rt];
	
	int mid=(l+r)>>1;
	if (nl<=mid)  return query(nl,l,mid,L[rt]);
	else return query(nl,mid+1,r,R[rt]);
}

int merge(int x,int y,int l,int r)
{
	if (!x)  return y;if (!y)  return x;
	if (l==r)
	{
		tree[x]+=tree[y];
		return x;
	}
	int mid=(l+r)>>1;
	L[x]=merge(L[x],L[y],l,mid);
	R[x]=merge(R[x],R[y],mid+1,r);
	pushup(x);
	
	return x;
}

void Merge(int x,int y)
{
	RT[x]=merge(RT[x],RT[y],1,n);
	fa[y]=x;
}

signed main()
{
	cin>>n>>m;
	for (int i=1;i<=n;i++)  cin>>a[i],fa[i]=i;
	for (int i=1;i<=n;i++)  RT[i]=change(a[i],1,n,RT[i],1);
	
	while (m--)
	{
		cin>>opt>>u>>v;
		if (opt==1)
		{
			int fx=fin(u),fy=fin(v);
			if (fx!=fy)  Merge(fx,fy);
		}
		else
		{
			int now=fin(u);
			cout<<query(v,1,n,RT[now])<<endl;
		}
	}
	return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define dup(x,y) (((x)+(y)-1)/(y))
#define ALL(x) (x).begin(), (x).end()
typedef long long ll;
typedef pair<int, int> pii;
const double EPS = 1e-10;
const int INF = 1e9;
const ll LINF = 1e18;
const int MOD = 1000000007;
const double PI = acos(-1);
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};

struct dsu {
	public:
		dsu(int n): cnt(n), par(n), siz(n, 1) {
			for (int i = 0; i < n; i++) par[i] = i;
		}
		bool merge(int x, int y) {
			x = find(x);
			y = find(y);
			if (x == y) return false;
			if (siz[x] < siz[y]) swap(x, y);
			siz[x] += siz[y];
			par[y] = x;
			--cnt;
			return true;
		}
		int find(int x) {
			return par[x] == x ? x : par[x] = find(par[x]);
		}
		int size(int x) {
			return siz[find(x)];
		}
		bool same(int x, int y) {
			return find(x) == find(y);
		}
		int groups() {
			return cnt;
		}
	private:
		int cnt;
		vector<int> par, siz;
};

int main() {
	int n, q;
	cin >> n >> q;
	dsu uf(n*2);
	map<int,int> ids;
	vector<map<int,int>> mps(n);
	rep(i,n) {
		int c;
		cin >> c;
		c--;
		ids[i] = c;
		mps[i][c]++;
	}
	rep(i,q) {
		int x, a, b;
		cin >> x >> a >> b;
		a--, b--;
		if (x == 1) {
			if (uf.same(a, b)) continue;
			if (uf.size(a) < uf.size(b)) {
				swap(a, b);
			}
			for (auto p: mps[uf.find(b)]) {
				mps[uf.find(a)][p.first] += p.second;
			}
			uf.merge(a, b);
		} else {
			cout << mps[uf.find(a)][b] << endl;
		}
	}
}