/****** BISMIintAH HIR RAHMANIR RAHIM ******/

#include <bits/stdc++.h>
using namespace std;
typedef pair<int ,int > pii;
#define NL cout<<endl;
#define DBG(a) cout<< #a <<" --> "<<(a)<<endl;
#define FastIO ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define IN freopen("input.txt","r+",stdin)
#define OUT freopen("output.txt","w+",stdout)

/****** stop OF HEADER ******/

#define mx 100005

int indeg[mx];
vector<int>g[mx];
int timer=0;
int start[mx];
int stop[mx];

int parent[mx];
int rnk[mx];
int given[mx];
vector < int > ques[mx];
unordered_map < int ,bool > anss[mx];
void dfs(int u)
{
    start[u]=++timer;
    for(int v : g[u])
    {
        dfs(v);
    }
    stop[u]=++timer;
}

int find_set(int v) {
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v]);
}

void make_set(int v) {
    parent[v] = v;
    rnk[v] = 0;
}

void union_sets(int a, int b) {
    a = find_set(a);
    b = find_set(b);
    if (a != b) {
        if (rnk[a] < rnk[b])
            swap(a, b);
        parent[b] = a;
        if (rnk[a] == rnk[b])
            rnk[a]++;
    }
}

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        make_set(i);
    }
    vector < pair < int ,pii > > inp;
    int total_pac=1;
    for(int i=0;i<m;i++)
    {
        int t,x,y;
        cin>>t>>x;
        if(t!=2) cin>>y;
        x--;
        if(t!=3) y--;
        inp.push_back({t,{x,y}});
        if(t==1)
        {
            indeg[x]++;
            g[y].push_back(x);
        }
        else if(t==3)
        {
            ques[y].push_back(x);
        }
    }
    for(int i=0;i<n;i++)
    {
        if(indeg[i]==0)
            dfs(i);
    }

    total_pac=1;
    for(pair < int ,pii > i : inp)
    {
        int t= i.first;
        int x= i.second.first;
        int y= i.second.second;
        if(t==1)
        {
            union_sets(x,y);
        }
        else if(t==2)
        {
            for(int j : ques[total_pac])
            {

                int ans=0;
                if(find_set(x)==find_set(j) && stop[j] >= start[x] && start[j] <= start[x])
                    ans=1;
//                DBG(x);
//                DBG(j);
//                DBG(total_pac);
//                DBG(ans);
//                NL;
                anss[total_pac][j]=ans;
            }
            total_pac++;
        }
        else
        {
            cout<<(anss[y][x] ?"YES\n": "NO\n");
        }
    }
    /*
    for(pair < int ,pii > i : inp)
    {
        int t= i.first;
        int x= i.second.first;
        int y= i.second.second;
        if(t==3)
        {
            cout<<(anss[y][x] ?"YES\n": "NO\n");
        }
    }
    */
}


/****** BISMIintAH HIR RAHMANIR RAHIM ******/

#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

typedef long long ll;
typedef pair <int, int> pii;
/* Special functions:

        find_by_order(k) --> returns iterator to the kth largest element counting from 0
        order_of_key(val) --> returns the number of items in a set that are strictly smainter than our item
*/

typedef tree<
int,
null_type,
less<int>,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;

#define EPS 1e-9
#define NL cout<<endl;
#define MP make_pair
#define Aint(a) a.begin(), a.end()
#define DBG(a) cout<< #a <<" --> "<<(a)<<endl;
#define FastIO ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define IN freopen("input.txt","r+",stdin)
#define OUT freopen("output.txt","w+",stdout)

template < class T1,class T2>
ostream &operator <<(ostream &os,const pair < T1,T2 > &p)
{
    os<<"{"<<p.first<<","<<p.second<<"}";
    return os;
}
template < class T1,class T2>
pair <T1,T2> operator + ( const  pair < T1,T2 > &p1,const pair < T1,T2 > &p2)
{
    return make_pair(p1.first+p2.first,p1.second+p2.second);
}
/****** END OF HEADER ******/

#define mx 100005

int parent[mx];
int rnk[mx];
int find_set(int v) {
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v]);
}

void make_set(int v) {
    parent[v] = v;
    rnk[v] = 0;
}

void union_sets(int a, int b) {
    a = find_set(a);
    b = find_set(b);
    if (a != b) {
        if (rnk[a] < rnk[b])
            swap(a, b);
        parent[b] = a;
        if (rnk[a] == rnk[b])
            rnk[a]++;
    }
}

int L[mx]; //লেভেল
int P[mx][22]; //স্পার্স টেবিল
int T[mx]; //প্যারেন্ট

int givento[mx];
int indeg[mx];
vector<int>g[mx];
void dfs(int from,int u,int dep)
{
    T[u]=from;
    L[u]=dep;
    for(int i=0; i<(int)g[u].size(); i++)
    {

        int v=g[u][i];
        if(v==from)
            continue;
        dfs(u,v,dep+1);
    }
}

int lca_query(int N, int p, int q) //N=নোড সংখ্যা
{
    int tmp, log, i;

    if (L[p] < L[q])
        tmp = p, p = q, q = tmp;

    log=1;
    while(1)
    {
        int next=log+1;
        if((1<<next)>L[p])
            break;
        log++;
    }

    for (i = log; i >= 0; i--)
        if (L[p] - (1 << i) >= L[q])
            p = P[p][i];

    if (p == q)
        return p;

    for (i = log; i >= 0; i--)
        if (P[p][i] != -1 && P[p][i] != P[q][i])
            p = P[p][i], q = P[q][i];

    return T[p];
}

void lca_init(int N)
{
    memset (P,-1,sizeof(P)); //শুরুতে সবগুলো ঘরে -১ থাকবে
    int i, j;
    for (i = 0; i < N; i++)
        P[i][0] = T[i];

    for (j = 1; 1 << j < N; j++)
        for (i = 0; i < N; i++)
            if (P[i][j - 1] != -1)
            {
                P[i][j] = P[P[i][j - 1]][j - 1];
            }

}

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++) make_set(i);
    vector < pair<int ,pii> > inp;
    for(int i=0;i<m;i++)
    {
        int t,x,y;
        cin>>t>>x;
        if(t!=2) cin>>y;
        x--;
        if(t==1) y--;
        inp.push_back({t,{x,y}});
        if(t==1)
        {
            g[y].push_back(x);
            indeg[x]++;
        }
    }
    int totalpacket=1;
    memset(T,-1,sizeof T);
    for(int i=0;i<n;i++)
    {
        if(indeg[i]==0)
        {

            dfs(-1,i,0);
        }
    }
    lca_init(n);
    for(pair<int ,pii>  i : inp)
    {
        int t= i.first,x= i.second.first,y=i.second.second;
        if(t==2)
        {
            givento[totalpacket++]=x;
        }
        else if(t==3)
        {
            int ans=0;
            if(find_set(x)==find_set(givento[y]))
            {
                int lc=lca_query(n,x,givento[y]);
                if(lc==x) ans=1;
            }
            cout<<(ans ? "YES\n" : "NO\n");
        }
        else
        {
            union_sets(x,y);
        }
    }

}


/****** BISMIintAH HIR RAHMANIR RAHIM ******/

#include <bits/stdc++.h>
using namespace std;
typedef pair<int ,int > pii;
#define NL cout<<endl;
#define DBG(a) cout<< #a <<" --> "<<(a)<<endl;
#define FastIO ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define IN freopen("input.txt","r+",stdin)
#define OUT freopen("output.txt","w+",stdout)

/****** stop OF HEADER ******/

#define mx 100005

int indeg[mx];
vector<int>g[mx];
int timer=0;
int start[mx];
int stop[mx];

int parent[mx];
int rnk[mx];
int given[mx];
vector < int > ques[mx];
unordered_map < int ,bool > anss[mx];
void dfs(int u)
{
    start[u]=++timer;
    for(int v : g[u])
    {
        dfs(v);
    }
    stop[u]=++timer;
}

int find_set(int v) {
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v]);
}

void make_set(int v) {
    parent[v] = v;
    rnk[v] = 0;
}

void union_sets(int a, int b) {
    a = find_set(a);
    b = find_set(b);
    if (a != b) {
        if (rnk[a] < rnk[b])
            swap(a, b);
        parent[b] = a;
        if (rnk[a] == rnk[b])
            rnk[a]++;
    }
}

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        make_set(i);
    }
    vector < pair < int ,pii > > inp;
    int total_pac=1;
    for(int i=0;i<m;i++)
    {
        int t,x,y;
        cin>>t>>x;
        if(t!=2) cin>>y;
        x--;
        if(t!=3) y--;
        inp.push_back({t,{x,y}});
        if(t==1)
        {
            indeg[x]++;
            g[y].push_back(x);
        }
        else if(t==3)
        {
            ques[y].push_back(x);
        }
    }
    for(int i=0;i<n;i++)
    {
        if(indeg[i]==0)
            dfs(i);
    }
    total_pac=1;
    for(pair < int ,pii > i : inp)
    {
        int t= i.first;
        int x= i.second.first;
        int y= i.second.second;
        if(t==1)
        {
            union_sets(x,y);
        }
        else if(t==2)
        {
            for(int j : ques[total_pac])
            {

                int ans=0;
                if(find_set(x)==find_set(j) && stop[x] > start[j])
                    ans=1;
                DBG(x);
                DBG(j);
                DBG(total_pac);
                DBG(ans);
                NL;
                anss[total_pac][j]=ans;
            }
            total_pac++;
        }
    }
    for(pair < int ,pii > i : inp)
    {
        int t= i.first;
        int x= i.second.first;
        int y= i.second.second;
        if(t==3)
        {
            cout<<(anss[y][x] ?"YES\n": "NO\n");
        }
    }
}


#include<vector>
#include<map>
#include<algorithm>
#include<set>
#include<iostream>
#include<string>
#include<set>
#include<queue>
#include<random>

using namespace std;

#pragma GCC optimize("Ofast")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,tune=native")

#define pb push_back
#define int long long
#define ld long double
#define ll long long
#define mp make_pair

mt19937 rnd(51);

const int N = 1e5 + 10;
int po[30][N];
vector<int> d(N, -1);
vector<int> g[N];
vector<bool> used(N);

void dfs(int v) {
	used[v] = 1;
	for (auto to : g[v]) {
		if (!used[to]) {
			d[to] = d[v] + 1;
			dfs(to);
		}
	}
}

int32_t main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	for (int i = 0; i < 30; i++) {
		for (int j = 0; j < N; j++) {
			po[i][j] = -1;
		}
	}
	map<int, int> nw;
	int n, m;
	cin >> n >> m;
	vector<int> ask;
	vector<pair<int, int>> v;
	for (int i = 0; i < m; i++) {
		int t;
		cin >> t;
		if (t == 1) {
			int x, y;
			cin >> x >> y;
			g[x].pb(y);
			g[y].pb(x);
			if (!used[y]) nw[y] = ask.size();
			if (!used[x]) nw[x] = ask.size();
			if (!used[y]) d[y] = 0;
			used[x] = used[y] = 1;
			d[x] = -1;
			po[0][x] = y;
		}
		else if (t == 2) {
			int v;
			cin >> v;
			ask.pb(v);
		}
		else {
			int v1, j;
			cin >> v1 >> j;
			j--;
			v.pb({ v1, j });
		}
	}
	fill(used.begin(), used.end(), 0);
	for (int i = 1; i <= n; i++) {
		if (d[i] == 0) {
			dfs(i);
		}
	}
	for (int i = 1; i < 30; i++) {
		for (int j = 1; j <= n; j++) {
			if (d[j] < (1 << i)) {
				po[i][j] = -1;
			}
			else {
				po[i][j] = po[i - 1][po[i - 1][j]];
			}
		}
	}
	int cnt = 1;
	for (auto to : v) {
		int u = to.first, vv = ask[to.second];
		if (nw[u] >= cnt) {
			cout << "NO" << endl;
			cnt++;
			continue;
		}
		cnt++;
		if (d[u] > d[vv]) {
			cout << "NO" << endl;
			continue;
		}
		else {
			for (int i = 29; i > -1; i--) {
				if (po[i][vv] != -1 &&  d[u] <= d[po[i][vv]]) {
					vv = po[i][vv];
				}
			}
			if (vv == u) {
				cout << "YES" << endl;
			}
			else {
				cout << "NO" << endl;
			}
		}
	}
	return 0;
}


#include<vector>
#include<map>
#include<algorithm>
#include<set>
#include<iostream>
#include<string>
#include<set>
#include<queue>
#include<random>

using namespace std;

#pragma GCC optimize("Ofast")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,tune=native")

#define pb push_back
#define int long long
#define ld long double
#define ll long long

const int N = 1e5 + 10;
vector<int> g[N];
vector<bool> used(N);
map<pair<int, int>, int> kek;
vector<int> d(N);
vector<int> par(N);
vector<int> ans;
vector<int> ind(N);
vector<int> t(N * 10);

void dfs(int v) {
	ans.pb(v);
	ind[v] = ans.size() - 1;
	used[v] = 1;
	for (auto to : g[v]) {
		if (!used[to]) {
			d[to] = d[v] + 1;
			dfs(to);
			ans.pb(v);
		}
	}
}

void build(int v, int l, int r) {
	if (l == r) {
		t[v] = d[ans[l]];
		return;
	}
	int m = (r + l) / 2;
	build(2 * v, l, m), build(2 * v + 1, m + 1, r);
	t[v] = min(t[v * 2], t[v * 2 + 1]);
}

int mn(int v, int tl, int tr, int l, int r) {
	if (tl == l && tr == r) {
		return t[v];
	}
	if (l > r) {
		return 1e9;
	}
	int tm = (tl + tr) / 2;
	return min(mn(2 * v, tl, tm, l, min(r, tm)), mn(2 * v + 1, tm + 1, tr, max(l, tm + 1), r));
}

int find_set(int a) {
	if (a == par[a])return a;
	else return par[a] = find_set(par[a]);
}

void union_set(int a, int b) {
	a = find_set(a);
	b = find_set(b);
	par[b] = a;
}

int32_t main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		par[i] = i;
	}
	vector<pair<int, pair<int, int>>> v;
	map<int, vector<int>> check;
	vector<int> now, good(n + 1, 1);
	for (int i = 0; i < m; i++) {
		int t;
		cin >> t;
		if (t == 1) {
			int x, y;
			cin >> x >> y;
			g[x].pb(y);
			g[y].pb(x);
			good[x] = 0;
			v.pb({ 1, {x, y} });
		}
		else if (t == 2) {
			int a;
			cin >> a;
			now.pb(a);
			v.pb({ 2, {now.size(), 0} });
		}
		else {
			int x, j;
			cin >> x >> j;
			check[j].pb(x);
			v.pb({ 3, {j, x} });
		}
	}
	for (int i = 1; i <= n; i++) {
		if (good[i]) {
			dfs(i);
		}
	}
	build(1, 0, ans.size() - 1);
	for (int i = 0; i < v.size(); i++) {
		if (v[i].first == 1) {
			int a = v[i].second.first, b = v[i].second.second;
			union_set(a, b);
		}
		else if (v[i].first == 2){
			int j = v[i].second.first;
			for (auto to : check[j]) {
				if (find_set(to) == find_set(now[j - 1])) {
					int p = min(ind[to], ind[now[j - 1]]), p1 = max(ind[to], ind[now[j - 1]]);
					int k = mn(1, 0, ans.size() - 1, p, p1);
					if (k == d[to] || k == d[now[j - 1]]) {
						kek[{j, to}] = 1;
					}
				}
			}
		}
	}
	for (int i = 0; i < v.size(); i++) {
		if (v[i].first == 3) {
			if (kek[v[i].second]) {
				cout << "YES" << endl;
			}
			else {
				cout << "NO" << endl;
			}
		}
	}
	return 0;
}


#include<vector>
#include<map>
#include<algorithm>
#include<set>
#include<iostream>
#include<string>
#include<set>
#include<queue>
#include<random>

using namespace std;

#pragma GCC optimize("Ofast")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,tune=native")

#define pb push_back
#define int long long
#define ld long double
#define ll long long
#define mp make_pair

mt19937 rnd(51);

const int N = 1e5 + 10;
int po[30][N];
vector<int> d(N, -1);
vector<int> g[N];
vector<bool> used(N);

void dfs(int v) {
	used[v] = 1;
	for (auto to : g[v]) {
		if (!used[to]) {
			d[to] = d[v] + 1;
			dfs(to);
		}
	}
}

void fll() {
	for (int i = 0; i < 30; i++)for (int j = 0; j < N; j++) po[i][j] = -1;
}

int32_t main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	fll();
	map<int, int> nw;
	int n, m;
	cin >> n >> m;
	vector<int> ask;
	vector<pair<int, int>> v;
	for (int i = 0; i < m; i++) {
		int t;
		cin >> t;
		if (t == 1) {
			int x, y;
			cin >> x >> y;
			g[x].pb(y);
			g[y].pb(x);
			if (!used[y]) nw[y] = ask.size();
			if (!used[x]) nw[x] = ask.size();
			if (!used[y]) d[y] = 0;
			used[x] = used[y] = 1;
			d[x] = -1;
			po[0][x] = y;
		}
		else if (t == 2) {
			int v;
			cin >> v;
			ask.pb(v);
		}
		else {
			int v1, j;
			cin >> v1 >> j;
			j--;
			v.pb({ v1, j });
		}
	}
	fill(used.begin(), used.end(), 0);
	for (int i = 1; i <= n; i++) {
		if (d[i] == 0) {
			dfs(i);
		}
	}
	for (int i = 1; i < 30; i++) {
		for (int j = 1; j <= n; j++) {
			if (d[j] < (1 << i)) {
				po[i][j] = -1;
			}
			else {
				po[i][j] = po[i - 1][po[i - 1][j]];
			}
		}
	}
	for (auto to : v) {
		int u = to.first, vv = ask[to.second];
		if (nw[u] >= to.second + 1) {
			cout << "NO" << endl;
			continue;
		}
		if (d[u] > d[vv]) {
			cout << "NO" << endl;
			continue;
		}
		else {
			for (int i = 29; i > -1; i--) {
				if (po[i][vv] != -1 &&  d[u] <= d[po[i][vv]]) {
					vv = po[i][vv];
				}
			}
			if (vv == u) {
				cout << "YES" << endl;
			}
			else {
				cout << "NO" << endl;
			}
		}
	}
	return 0;
}


#include<vector>
#include<map>
#include<algorithm>
#include<set>
#include<iostream>
#include<string>
#include<set>
#include<queue>
#include<random>

using namespace std;

#pragma GCC optimize("Ofast")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,tune=native")

#define pb push_back
#define int long long
#define ld long double
#define ll long long

const int N = 1e5 + 10;
vector<int> g[N];
vector<int> d(N);
vector<bool> used(N);
map<pair<int, int>, int> ans;
vector<int> par(N);

void dfs(int v) {
	used[v] = 1;
	for (auto to : g[v]) {
		if (!used[to]) {
			d[to] = d[v] + 1;
			dfs(to);
		}
	}
}

int find_set(int a) {
	if (a == par[a])return a;
	else return par[a] = find_set(par[a]);
}

void union_set(int a, int b) {
	a = find_set(a);
	b = find_set(b);
	par[b] = a;
}

int32_t main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		par[i] = i;
	}
	vector<pair<int, pair<int, int>>> v;
	map<int, vector<int>> check;
	vector<int> now, good(n + 1, 1);
	for (int i = 0; i < m; i++) {
		int t;
		cin >> t;
		if (t == 1) {
			int x, y;
			cin >> x >> y;
			g[x].pb(y);
			g[y].pb(x);
			good[x] = 0;
			v.pb({ 1, {x, y} });
		}
		else if (t == 2) {
			int a;
			cin >> a;
			now.pb(a);
			v.pb({ 2, {now.size(), 0} });
		}
		else {
			int x, j;
			cin >> x >> j;
			if (now.size() >= j) {
				check[j].pb(x);
			}
			v.pb({ 3, {j, x} });
		}
	}
	for (int i = 1; i <= n; i++) {
		if (good[i]) {
			dfs(i);
		}
	}
	for (int i = 0; i < v.size(); i++) {
		if (v[i].first == 1) {
			int a = v[i].second.first, b = v[i].second.second;
			union_set(a, b);
		}
		else if (v[i].first == 2){
			int j = v[i].second.first;
			for (auto to : check[j]) {
				if (d[now[j - 1]] >= d[to] && find_set(to) == find_set(now[j - 1])) {
					ans[{j, to}] = 1;
				}
			}
		}
	}
	for (int i = 0; i < v.size(); i++) {
		if (v[i].first == 3) {
			if (ans[v[i].second]) {
				cout << "YES" << endl;
			}
			else {
				cout << "NO" << endl;
			}
		}
	}
	return 0;
}


#include<vector>
#include<map>
#include<algorithm>
#include<set>
#include<iostream>
#include<string>
#include<set>
#include<queue>
#include<random>

using namespace std;

#pragma GCC optimize("Ofast")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,tune=native")

#define pb push_back
#define int long long
#define ld long double
#define ll long long

const int N = 1e5 + 10;
vector<int> g[N];
vector<bool> used(N);
map<pair<int, int>, int> kek;
vector<int> d(N);
vector<int> par(N);
vector<int> ans;
vector<int> ind(N);
vector<int> t(N * 10);

void dfs(int v) {
	ans.pb(v);
	ind[v] = ans.size() - 1;
	used[v] = 1;
	for (auto to : g[v]) {
		if (!used[to]) {
			d[to] = d[v] + 1;
			dfs(to);
			ans.pb(v);
		}
	}
}

void build(int v, int l, int r) {
	if (l == r) {
		t[v] = d[ans[l]];
		return;
	}
	int m = (r + l) / 2;
	build(2 * v, l, m), build(2 * v + 1, m + 1, r);
	t[v] = min(t[v * 2], t[v * 2 + 1]);
}

int mn(int v, int tl, int tr, int l, int r) {
	if (tl == l && tr == r) {
		return t[v];
	}
	if (l > r) {
		return 1e9;
	}
	int tm = (tl + tr) / 2;
	return min(mn(2 * v, tl, tm, l, min(r, tm)), mn(2 * v + 1, tm + 1, tr, max(l, tm + 1), r));
}

int find_set(int a) {
	if (a == par[a])return a;
	else return par[a] = find_set(par[a]);
}

void union_set(int a, int b) {
	a = find_set(a);
	b = find_set(b);
	par[b] = a;
}

int32_t main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		par[i] = i;
	}
	vector<pair<int, pair<int, int>>> v;
	map<int, vector<int>> check;
	vector<int> now, good(n + 1, 1);
	for (int i = 0; i < m; i++) {
		int t;
		cin >> t;
		if (t == 1) {
			int x, y;
			cin >> x >> y;
			g[x].pb(y);
			g[y].pb(x);
			good[x] = 0;
			v.pb({ 1, {x, y} });
		}
		else if (t == 2) {
			int a;
			cin >> a;
			now.pb(a);
			v.pb({ 2, {now.size(), 0} });
		}
		else {
			int x, j;
			cin >> x >> j;
			check[j].pb(x);
			v.pb({ 3, {j, x} });
		}
	}
	for (int i = 1; i <= n; i++) {
		if (good[i]) {
			dfs(i);
		}
	}
	build(1, 0, ans.size() - 1);
	for (int i = 0; i < v.size(); i++) {
		if (v[i].first == 1) {
			int a = v[i].second.first, b = v[i].second.second;
			union_set(a, b);
		}
		else if (v[i].first == 2){
			int j = v[i].second.first;
			for (auto to : check[j]) {
				if (find_set(to) == find_set(now[j - 1])) {
					int p = min(ind[to], ind[now[j - 1]]), p1 = max(ind[to], ind[now[j - 1]]);
					int k = mn(1, 0, ans.size() - 1, p, p1);
					if (k == d[to]) {
						kek[{j, to}] = 1;
					}
				}
			}
		}
	}
	for (int i = 0; i < v.size(); i++) {
		if (v[i].first == 3) {
			if (kek[v[i].second]) {
				cout << "YES" << endl;
			}
			else {
				cout << "NO" << endl;
			}
		}
	}
	return 0;
}


#include<bits/stdc++.h>
#include<math.h>
#define rep(i,k,n) for(int i=k;i<n;i++)
#define ll long long
#define MOD 998244353
#define ROD 1000000009
#define INF 0x3f3f3f3f3f3f3f3f
#define MIN(a,b) (a>b?b:a)
#define fi first
#define se second
#define pii pair<ll,ll>
#define piii pair<pair<ll,ll>,pair<ll,ll>>
#define mp make_pair
using namespace std;
ll w,x,y,t=1,n,q,pr[100005][21],mr[100005][21],tr[100005][2];
ll qno,pno=1;
vector <ll> vr[100005];
pii pac[100005];
pii qr[100005];
void pre(),post(),dfs(ll);
ll query(ll,ll);
int main()
{
	pre();
	cin>>n>>q;
	rep(i,0,q)
	{
		cin>>w;
		if(w==1)
		{
			cin>>x>>y;
			vr[y].push_back(x);
			pr[x][0]=y;
			mr[x][0]=t++;
		}
		else if(w==2)
		{
			cin>>x;
			pac[pno++]=mp(x,t++);
		}
		else
		{
			cin>>x>>y;
			qr[qno++]=mp(x,y);
		}

	}
	post();
	// rep(i,1,n+1)
	// {
	// 	rep(j,0,4)
	// 	cout<<mr[i][j]<<" ";
	// 	cout<<"\n";
	// }
	rep(i,0,qno)
	{
		if(query(qr[i].fi,qr[i].se))
			cout<<"YES\n";
		else
			cout<<"NO\n";
	}
}
void pre()
{
	rep(i,0,100005)
	pr[i][0]=-1;
}
void post()
{
	rep(i,1,20)
	rep(j,1,n+1)
	{
		if(pr[j][i-1]==-1)
			pr[j][i]=-1;
		else
		{
			pr[j][i]=pr[pr[j][i-1]][i-1];
			mr[j][i]=max(mr[pr[j][i-1]][i-1],mr[j][i-1]);
		}
	}
	t=0;
	rep(i,1,n+1)
	if(pr[i][0]==-1)
		dfs(i);
}
void dfs(ll idx)
{
	tr[idx][0]=t++;
	rep(i,0,vr[idx].size())
	dfs(vr[idx][i]);
	tr[idx][1]=t++;
}
ll query(ll idx,ll i)
{
	//cout<<idx<<" "<<i<<" ";
	if(idx==pac[i].fi)
		return 1;
	ll v=pac[i].fi,max_=0;
	for(int i=19;i>=0;i--)
	{
		if(pr[v][i]==-1)
			continue;
		ll temp=pr[v][i];
		if(tr[idx][0]<=tr[temp][0]&&tr[temp][1]<=tr[idx][1])
		{
			max_=max(max_,mr[v][i]);
			v=pr[v][i];
			// cout<<v<<" "<<pr[v][i]<<" "<<mr[v][i]<<" PPP\n";
		}
	}
	//cout<<v<<" "<<idx<<" "<<max_<<" "<<pac[i].fi<<" "<<pac[i].se<<" AA\n";
	if(v==idx&&max_<=pac[i].se)
		return 1;
	return 0;
}


#include<bits/stdc++.h>
#include<math.h>
#define rep(i,k,n) for(int i=k;i<n;i++)
#define ll long long
#define MOD 998244353
#define ROD 1000000009
#define INF 0x3f3f3f3f3f3f3f3f
#define MIN(a,b) (a>b?b:a)
#define fi first
#define se second
#define pii pair<ll,ll>
#define piii pair<pair<ll,ll>,pair<ll,ll>>
#define mp make_pair
using namespace std;
ll w,x,y,t=1,n,q,pr[100005][21],mr[100005][21],tr[100005][2];
ll qno,pno=1;
vector <ll> vr[100005];
pii pac[100005];
pii qr[100005];
void pre(),post(),dfs(ll);
ll query(ll,ll);
int main()
{
	pre();
	cin>>n>>q;
	rep(i,0,q)
	{
		cin>>w;
		if(w==1)
		{
			cin>>x>>y;
			vr[y].push_back(x);
			pr[x][0]=y;
			mr[x][0]=t++;
		}
		else if(w==2)
		{
			cin>>x;
			pac[pno++]=mp(x,t++);
		}
		else
		{
			cin>>x>>y;
			qr[qno++]=mp(x,y);
		}

	}
	post();
	// rep(i,1,n+1)
	// {
	// 	rep(j,0,4)
	// 	cout<<mr[i][j]<<" ";
	// 	cout<<"\n";
	// }
	rep(i,0,qno)
	{
		if(query(qr[i].fi,qr[i].se))
			cout<<"YES\n";
		else
			cout<<"NO\n";
	}
}
void pre()
{
	rep(i,0,100005)
	pr[i][0]=-1;
}
void post()
{
	rep(i,1,20)
	rep(j,1,n+1)
	{
		if(pr[j][i-1]==-1)
			pr[j][i]=-1;
		else
		{
			pr[j][i]=pr[pr[j][i-1]][i-1];
			mr[j][i]=max(mr[pr[j][i-1]][i-1],mr[j][i-1]);
		}
	}
	t=0;
	rep(i,1,n+1)
	if(pr[i][0]==-1)
		dfs(i);
}
void dfs(ll idx)
{
	tr[idx][0]=t++;
	rep(i,0,vr[idx].size())
	dfs(vr[idx][i]);
	tr[idx][1]=t++;
}
ll query(ll idx,ll i)
{
	//cout<<idx<<" "<<i<<" ";
	if(idx==pac[i].fi)
		return 1;
	ll v=pac[i].fi,max_=0;
	for(int i=20;i>=0;i--)
	{
		if(pr[v][i]==-1)
			continue;
		ll temp=pr[v][i];
		if(tr[idx][0]<=tr[temp][0]&&tr[temp][1]<=tr[idx][1])
		{
			max_=max(max_,mr[v][i]);
			v=pr[v][i];
			// cout<<v<<" "<<pr[v][i]<<" "<<mr[v][i]<<" PPP\n";
		}
	}
	//cout<<v<<" "<<idx<<" "<<max_<<" "<<pac[i].fi<<" "<<pac[i].se<<" AA\n";
	if(v==idx&&max_<=pac[i].se)
		return 1;
	return 0;
}


#include<bits/stdc++.h>
#include<math.h>
#define rep(i,k,n) for(int i=k;i<n;i++)
#define ll long long
#define MOD 998244353
#define ROD 1000000009
#define INF 0x3f3f3f3f3f3f3f3f
#define MIN(a,b) (a>b?b:a)
#define fi first
#define se second
#define pii pair<ll,ll>
#define piii pair<pair<ll,ll>,pair<ll,ll>>
#define mp make_pair
using namespace std;
ll w,x,y,t=1,n,q,pr[100005][20],mr[100005][20],tr[100005][2];
ll qno,pno=1;
vector <ll> vr[100005];
pii pac[100005];
pii qr[100005];
void pre(),post(),dfs(ll);
ll query(ll,ll);
int main()
{
	pre();
	cin>>n>>q;
	rep(i,0,q)
	{
		cin>>w;
		if(w==1)
		{
			cin>>x>>y;
			vr[y].push_back(x);
			pr[x][0]=y;
			mr[x][0]=t++;
		}
		else if(w==2)
		{
			cin>>x;
			pac[pno++]=mp(x,t++);
		}
		else
		{
			cin>>x>>y;
			qr[qno++]=mp(x,y);
		}

	}
	post();
	// rep(i,1,n+1)
	// {
	// 	rep(j,0,4)
	// 	cout<<mr[i][j]<<" ";
	// 	cout<<"\n";
	// }
	rep(i,0,qno)
	{
		if(query(qr[i].fi,qr[i].se))
			cout<<"YES\n";
		else
			cout<<"NO\n";
	}
}
void pre()
{
	rep(i,0,100005)
	pr[i][0]=-1;
}
void post()
{
	rep(i,1,20)
	rep(j,1,n+1)
	{
		if(pr[j][i-1]==-1)
			pr[j][i]=-1;
		else
		{
			pr[j][i]=pr[pr[j][i-1]][i-1];
			mr[j][i]=max(mr[pr[j][i-1]][i-1],mr[j][i-1]);
		}
	}
	t=0;
	rep(i,1,n+1)
	if(pr[i][0]==-1)
		dfs(i);
}
void dfs(ll idx)
{
	tr[idx][0]=t++;
	rep(i,0,vr[idx].size())
	dfs(vr[idx][i]);
	tr[idx][1]=t++;
}
ll query(ll idx,ll i)
{
	//cout<<idx<<" "<<i<<" ";
	if(idx==pac[i].fi)
		return 1;
	ll v=pac[i].fi,max_=0;
	for(int i=20;i>=0;i--)
	{
		if(pr[v][i]==-1)
			continue;
		ll temp=pr[v][i];
		if(tr[idx][0]<=tr[temp][0]&&tr[temp][1]<=tr[idx][1])
		{
			max_=max(max_,mr[v][i]);
			v=pr[v][i];
			// cout<<v<<" "<<pr[v][i]<<" "<<mr[v][i]<<" PPP\n";
		}
	}
	//cout<<v<<" "<<idx<<" "<<max_<<" "<<pac[i].fi<<" "<<pac[i].se<<" AA\n";
	if(v==idx&&max_<=pac[i].se)
		return 1;
	return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define all(x) (x).begin(), (x).end()

using namespace __gnu_pbds;
using namespace std;

using ull = unsigned long long;
using ll = long long;
using ld = long double;
template <typename T> using ordered_set = tree<T, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update>;

const int mod = 1e9 + 7;
const int inf = INT_MAX;
const int N = 1e5 + 5;

class UnionFind {
public:
    int n;
    vector<int> p, r;
    explicit UnionFind(int n = 0): n(n), p(n + 1), r(n + 1) {
        iota(all(p), 0);
    }
    int size() const {
        return n;
    }
    int find(int x) {
        if (p[x] != x)
            p[x] = find(p[x]);
        return p[x];
    }
    void union_find(int x, int y) {
        int l1 = find(x);
        int l2 = find(y);

        if (l1 != l2) {
            if (r[l1] > r[l2])
                p[l2] = l1;
            else if (r[l1] < r[l2])
                p[l1] = l2;
            else {
                p[l2] = l1;
                r[l1]++;
            }
            n--;
        }
    }
};

int n, m, l[N], p[N], tin[N], tout[N], T;
vector<int> g[N];

void dfs(int x) {
    tin[x] = T++;

    for (int &i : g[x]) {
        if (i == p[x]) continue;
        dfs(i);
    }

    tout[x] = T++;
}

bool f(int u, int v) {
    return tin[u] <= tin[v] and tout[u] >= tout[v];
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> m;
    UnionFind uf(n);

    vector<pair<int, int>> q1, q2;
    iota(l, l + n + 1, 0);

    while (m--) {
        int t;
        cin >> t;

        if (t == 1) {
            int x, y;
            cin >> x >> y;
            g[x].push_back(y);
            g[y].push_back(x);

            l[uf.find(x)] = l[uf.find(y)];
            uf.union_find(x, y);
            p[x] = y;
        }
        else if (t == 2) {
            int x;
            cin >> x;
            q1.emplace_back(l[uf.find(x)], x);
        }
        else {
            int x, i;
            cin >> x >> i; --i;

            q2.emplace_back(x, i);
        }
    }

    for (int i = 1; i <= n; i++) {
        if (!p[i]) {
            dfs(i);
        }
    }

    for (auto &[x, i]: q2) {
        if (f(q1[i].first, x) and f(x, q1[i].second))
            cout << "YES\n";
        else cout << "NO\n";
    }
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define all(x) (x).begin(), (x).end()

using namespace __gnu_pbds;
using namespace std;

using ull = unsigned long long;
using ll = long long;
using ld = long double;
template <typename T> using ordered_set = tree<T, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update>;

const int mod = 1e9 + 7;
const int inf = INT_MAX;
const int N = 1e5 + 5;

class UnionFind {
public:
    int n;
    vector<int> p, r;
    explicit UnionFind(int n = 0): n(n), p(n + 1), r(n + 1) {
        iota(all(p), 0);
    }
    int size() const {
        return n;
    }
    int find(int x) {
        if (p[x] != x)
            p[x] = find(p[x]);
        return p[x];
    }
    void union_find(int x, int y) {
        int l1 = find(x);
        int l2 = find(y);

        if (l1 != l2) {
            if (r[l1] > r[l2])
                p[l2] = l1;
            else if (r[l1] < r[l2])
                p[l1] = l2;
            else {
                p[l2] = l1;
                r[l1]++;
            }
            n--;
        }
    }
};

int n, m, lead[N], p[N], tin[N], tout[N], T;
vector<int> g[N];

vector<pair<int, int>> q1, q2;

void dfs(int x) {
    tin[x] = T++;

    for (int &i : g[x]) {
        if (i == p[x]) continue;
        dfs(i);
    }

    tout[x] = T++;
}

bool f(int u, int v) {
    return tin[u] <= tin[v] and tout[u] >= tout[v];
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> m;
    UnionFind uf(n);

    while (m--) {
        int t;
        cin >> t;

        if (t == 1) {
            int x, y;
            cin >> x >> y;
            g[x].push_back(y);
            g[y].push_back(x);

            uf.union_find(x, y);
            lead[uf.find(y)] = y;
            p[x] = y;
        }
        else if (t == 2) {
            int x;
            cin >> x;
            q1.emplace_back(lead[uf.find(x)], x);
        }
        else {
            int x, i;
            cin >> x >> i; --i;

            q2.emplace_back(x, i);
        }
    }

    for (int i = 1; i <= n; i++) {
        if (!p[i]) {
            dfs(i);
        }
    }

    for (auto &[x, i]: q2) {
        if (f(q1[i].first, x) and f(x, q1[i].second))
            cout << "YES\n";
        else cout << "NO\n";
    }
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define all(x) (x).begin(), (x).end()

using namespace __gnu_pbds;
using namespace std;

using ull = unsigned long long;
using ll = long long;
using ld = long double;
template <typename T> using ordered_set = tree<T, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update>;

const int mod = 1e9 + 7;
const int inf = INT_MAX;
const int N = 1e5 + 5;

class UnionFind {
public:
    int n;
    vector<int> p, r;
    explicit UnionFind(int n = 0): n(n), p(n + 1), r(n + 1) {
        iota(all(p), 0);
    }
    int size() const {
        return n;
    }
    int find(int x) {
        if (p[x] != x)
            p[x] = find(p[x]);
        return p[x];
    }
    void union_find(int x, int y) {
        int l1 = find(x);
        int l2 = find(y);

        if (l1 != l2) {
            if (r[l1] > r[l2])
                p[l2] = l1;
            else if (r[l1] < r[l2])
                p[l1] = l2;
            else {
                p[l2] = l1;
                r[l1]++;
            }
            n--;
        }
    }
};

int n, m, lead[N], p[N], tin[N], tout[N], T;
vector<int> g[N];

void dfs(int x) {
    tin[x] = T++;

    for (int &i : g[x]) {
        if (i == p[x]) continue;
        dfs(i);
    }

    tout[x] = T++;
}

bool f(int u, int v) {
    return tin[u] <= tin[v] and tout[u] >= tout[v];
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> m;
    UnionFind uf(n);

    vector<pair<int, int>> q1, q2;
    iota(lead, lead + n + 1, 0);

    while (m--) {
        int t;
        cin >> t;

        if (t == 1) {
            int x, y;
            cin >> x >> y;
            g[x].push_back(y);
            g[y].push_back(x);

            uf.union_find(x, y);
            lead[uf.find(y)] = y;
            p[x] = y;
        }
        else if (t == 2) {
            int x;
            cin >> x;
            q1.emplace_back(lead[uf.find(x)], x);
        }
        else {
            int x, i;
            cin >> x >> i; --i;

            q2.emplace_back(x, i);
        }
    }

    for (int i = 1; i <= n; i++) {
        if (!p[i]) {
            dfs(i);
        }
    }

    for (auto &[x, i]: q2) {
        if (f(q1[i].first, x) and f(x, q1[i].second))
            cout << "YES\n";
        else cout << "NO\n";
    }
    return 0;
}


#include <bits/stdc++.h>
typedef long long int ll;
typedef long double ld;
#define pb push_back
#define pii pair < int , int >
#define F first
#define S second
#define int long long int
#define sync ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#pragma GCC optimize ("Ofast")
using namespace std;
/// khodaya komak kon
/// ya navid navid
const int N=1e5+10;
ll par[N];

vector <int> g[N];

ll getpar(ll v){
    if (par[v]!=v){
        return par[v]=getpar(par[v]);
    }
    return v;
}
vector <pii> ask;
vector <pii> pack;
ll s[N];
ll f[N];
ll s1=0,f1=0;
ll dfs(ll v,ll p){
    s[v]=s1;
    for (int i=0;i<g[v].size();i++){
        ll u=g[v][i];
        if (u!=p){
            s1++;
            dfs(u,v);
        }
    }
    f[v]=f1;
    f1++;
}
int32_t main(){
    ll n,m;
    cin >> n >> m;
    for (int i=0;i<N;i++){
        par[i]=i;
    }
    for (int i=0;i<m;i++){

        ll t;
        cin >> t;
        ll x,y;
        if (t==1){
            cin >> x >> y;
            g[x].pb(y);
            g[y].pb(x);
            par[x]=y;
        }
        if (t==2){
            ll x;
            cin >> x;
            pack.pb({x,getpar(x)});
            //cout << x << " mkrf " << getpar(x) << endl;
        }
        if (t==3){
            ll x,y;
            cin >> x >> y;
            ask.pb({y,x});
        }

    }
    dfs(getpar(1),-1);
    for (int i=0;i<ask.size();i++){
        ll b=ask[i].S;
        ll u=ask[i].F;
        ll v=pack[b-1].S;
        ll w=pack[b-1].F;
        //cout << u << " " << v << " " << w << endl;
        if (s[v]<=s[u] && f[v]>=f[u] && s[u]<=s[w] && f[u]>=f[w]){
            cout << "YES" << endl;
        }
        else{
            cout << "NO" << endl;
        }
    }
}


#include <bits/stdc++.h>
typedef long long int ll;
typedef long double ld;
#define pb push_back
#define pii pair < int , int >
#define F first
#define S second
#define int long long int
#define sync ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#pragma GCC optimize ("Ofast")
using namespace std;
/// khodaya komak kon
/// ya navid navid
const int N=1e5+10;
ll par[N];

vector <int> g[N];

ll getpar(ll v){
    if (par[v]!=v){
        return par[v]=getpar(par[v]);
    }
    return v;
}
vector <pii> ask;
vector <pii> pack;
ll s[N];
ll f[N];
ll s1=0,f1=0;
ll dfs(ll v,ll p){
    s[v]=s1;
    for (int i=0;i<g[v].size();i++){
        ll u=g[v][i];
        if (u!=p){
            s1++;
            dfs(u,v);
        }
    }
    f[v]=f1;
    f1++;
}
int32_t main(){
    ll n,m;
    cin >> n >> m;
    for (int i=0;i<N;i++){
        par[i]=i;
    }
    for (int i=0;i<m;i++){

        ll t;
        cin >> t;
        ll x,y;
        if (t==1){
            cin >> x >> y;
            g[x].pb(y);
            g[y].pb(x);
            par[x]=y;
        }
        if (t==2){
            ll x;
            cin >> x;
            pack.pb({x,getpar(x)});
            //cout << x << " mkrf " << getpar(x) << endl;
        }
        if (t==3){
            ll x,y;
            cin >> x >> y;
            ask.pb({y,x});
        }

    }
    dfs(getpar(1),-1);
    for (int i=0;i<ask.size();i++){
        ll b=ask[i].F;
        ll u=ask[i].S;
        ll v=pack[b-1].S;
        ll w=pack[b-1].F;
       // cout << u << " " << v << " " << w << " " << b << endl;
        if (s[v]<=s[u] && f[v]>=f[u] && s[u]<=s[w] && f[u]>=f[w]){
            cout << "YES" << endl;
        }
        else{
            cout << "NO" << endl;
        }
    }
}


#include <bits/stdc++.h>
typedef long long int ll;
typedef long double ld;
#define pb push_back
#define pii pair < int , int >
#define F first
#define S second
#define int long long int
#define sync ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#pragma GCC optimize ("Ofast")
using namespace std;
/// khodaya komak kon
/// ya navid navid
const int N=1e5+10;
ll par[N];

vector <int> g[N];
ll visit[N];
ll getpar(ll v){
    if (par[v]!=v){
        return par[v]=getpar(par[v]);
    }
    return v;
}
vector <pii> ask;
vector <pii> pack;
ll s[N];
ll f[N];
ll s1=0,f1=0;
ll dfs(ll v,ll p){
    s[v]=s1;
    visit[v]=1;
    for (int i=0;i<g[v].size();i++){
        ll u=g[v][i];
        if (u!=p){
            s1++;
            dfs(u,v);
        }
    }
    f[v]=f1;
    f1++;
}
int32_t main(){
    ll n,m;
    cin >> n >> m;
    for (int i=0;i<N;i++){
        par[i]=i;
    }
    for (int i=0;i<m;i++){

        ll t;
        cin >> t;
        ll x,y;
        if (t==1){
            cin >> x >> y;
            g[x].pb(y);
            g[y].pb(x);
            par[x]=y;
        }
        if (t==2){
            ll x;
            cin >> x;
            ll k=getpar(x);
            pack.pb({x,k});
            //cout << x << " SV " << pack.size() << " mkrf " << k << endl;
        }
        if (t==3){
            ll x,y;
            cin >> x >> y;
            ask.pb({y,x});
        }

    }
    for (int i=1;i<=n;i++){
        if (visit[i]==0){
            dfs(getpar(i),-1);
        }
    }
    dfs(getpar(1),-1);
    for (int i=0;i<ask.size();i++){
        ll b=ask[i].F;
        ll u=ask[i].S;
        ll v=pack[b-1].S;
        ll w=pack[b-1].F;
        //cout << u << " " << v << " " << w << " " << b << " " << s[v] << " " << s[u]  << endl;
        if (s[v]<=s[u] && f[v]>=f[u] && s[u]<=s[w] && f[u]>=f[w]){
            cout << "YES" << endl;
        }
        else{
            cout << "NO" << endl;
        }
    }
    /*
10 5
1 5 4
2 5
2 3
3 7 2
1 8 4
*/

}


#include <bits/stdc++.h>
typedef long long int ll;
typedef long double ld;
#define pb push_back
#define pii pair < int , int >
#define F first
#define S second
#define int long long int
#define sync ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#pragma GCC optimize ("Ofast")
using namespace std;
/// khodaya komak kon
/// ya navid navid
const int N=1e5+10;
ll par[N];

vector <int> g[N];
ll visit[N];
ll getpar(ll v){
    if (par[v]!=v){
        return par[v]=getpar(par[v]);
    }
    return v;
}
vector <pii> ask;
vector <pii> pack;
ll s[N];
ll f[N];
ll s1=0,f1=0;
ll dfs(ll v,ll p){
    s[v]=s1;
    visit[v]=1;
    for (int i=0;i<g[v].size();i++){
        ll u=g[v][i];
        if (u!=p){
            s1++;
            dfs(u,v);
        }
    }
    f[v]=f1;
    f1++;
}
int32_t main(){
    ll n,m;
    cin >> n >> m;
    for (int i=0;i<N;i++){
        par[i]=i;
    }
    for (int i=0;i<m;i++){

        ll t;
        cin >> t;
        ll x,y;
        if (t==1){
            cin >> x >> y;
            g[x].pb(y);
            g[y].pb(x);
            par[x]=y;
        }
        if (t==2){
            ll x;
            cin >> x;
            ll k=getpar(x);
            pack.pb({x,k});
            cout << x << " SV " << pack.size() << " mkrf " << k << endl;
        }
        if (t==3){
            ll x,y;
            cin >> x >> y;
            ask.pb({y,x});
        }

    }
    for (int i=1;i<=n;i++){
        if (visit[i]==0){
            dfs(getpar(i),-1);
        }
    }
    dfs(getpar(1),-1);
    for (int i=0;i<ask.size();i++){
        ll b=ask[i].F;
        ll u=ask[i].S;
        ll v=pack[b-1].S;
        ll w=pack[b-1].F;
        cout << u << " " << v << " " << w << " " << b << " " << s[v] << " " << s[u]  << endl;
        if (s[v]<=s[u] && f[v]>=f[u] && s[u]<=s[w] && f[u]>=f[w]){
            cout << "YES" << endl;
        }
        else{
            cout << "NO" << endl;
        }
    }
    /*
10 5
1 5 4
2 5
2 3
3 7 2
1 8 4
*/

}


#include <bits/stdc++.h>
using namespace std;
const int inf=1e5+9;
int n,m,type[inf],x[inf],y[inf],in[inf],out[inf],timer=1,par[inf],em[inf];
vector<int> v[inf];
vector<pair<int,int> > ans;

void dfs(int node,int par){

    in[node]=timer++;
    for(auto o:v[node])
        if(o!=par)
            dfs(o,node);

    out[node]=timer-1;
}

int root(int x){

    if(x==par[x])
        return x;
    return par[x]=root(par[x]);
}

void connect(int x,int y){

    x=root(x),y=root(y);
    if(x==y)
        return ;
    if(rand()%2)
        swap(x,y);

    par[x]=y;
}

int main(){

    cin>>n>>m;

    for(int i=1;i<=n;i++)
        par[i]=i;

    for(int i=1;i<=m;i++){
        cin>>type[i]>>x[i];
        if(type[i]!=2)
            cin>>y[i];

        if(type[i]==1)
            v[y[i]].push_back(x[i]);
    }

    for(int i=1;i<=n;i++)
        if(in[i]==0 && v[i].size()>0)
            dfs(i,0);

    int cnt_packet=0;
    for(int i=1;i<=m;i++){

        if(type[i]==1)
            connect(x[i],y[i]);

        else if(type[i]==2)
            cnt_packet++,em[cnt_packet]=x[i];

        else
            cout<<( root(x[i])==root(em[y[i]] ) && in[x[i]]<=in[em[y[i]]] && out[x[i]]>=out[em[y[i]]] ?"YES":"NO"  )<<endl;

    }
}


#include <bits/stdc++.h>
using namespace std;
const int inf=1e5+9;
int n,m,type[inf],x[inf],y[inf],in[inf],out[inf],timer=1,par[inf],em[inf],sz[inf];
vector<int> v[inf];
vector<pair<int,int> > ans;

void dfs(int node,int par){

    in[node]=timer++;
    for(auto o:v[node])
        if(o!=par && in[o]==0)
            dfs(o,node);

    out[node]=timer++;
}

int root(int x){

    if(x==par[x])
        return x;

    return par[x]=root(par[x]);
}

void connect(int x,int y){

    x=root(x),y=root(y);
    if(x==y)
        return ;

    if(sz[x]>sz[y])
        swap(x,y);

    par[x]=y;
    sz[y]+=sz[x];
}

int main(){

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        par[i]=i,sz[i]=1;

    for(int i=1;i<=m;i++){

        scanf("%d%d",&type[i],&x[i]);

        if(type[i]!=2)
            scanf("%d",&y[i]);

        if(type[i]==1)
            v[y[i]].push_back(x[i]),deg[x[i]]++;
    }

    for(int i=1;i<=n;i++)
        if(in[i]==0 &&deg[i]==0)
            dfs(i,0);

    int cnt_packet=0;
    for(int i=1;i<=m;i++){

        if(type[i]==1)
            connect(x[i],y[i]);

        else if(type[i]==2)
            cnt_packet++,em[cnt_packet]=x[i];

        else{
            if( root(x[i])==root(em[y[i]] ) && in[x[i]]<=in[em[y[i]]] && out[x[i]]>=out[em[y[i]]])
                printf("YES\n");
            else
                printf("NO\n");
        }

    }
}


#include <bits/stdc++.h>
using namespace std;
const int inf=1e5+9;
int n,m,type[inf],x[inf],y[inf],in[inf],out[inf],timer=1,par[inf],em[inf],sz[inf];
vector<int> v[inf];
vector<pair<int,int> > ans;

void dfs(int node,int par){

    in[node]=timer++;
    for(auto o:v[node])
        if(o!=par)
            dfs(o,node);

    out[node]=timer-1;
}

int root(int x){

    if(x==par[x])
        return x;
    return par[x]=root(par[x]);
}

void connect(int x,int y){

    x=root(x),y=root(y);
    if(x==y)
        return ;
    if(sz[x]>sz[y])
        swap(x,y);

    par[x]=y;
    sz[y]+=sz[x];
}

int main(){

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        par[i]=i,sz[i]=1;

    for(int i=1;i<=m;i++){

        scanf("%d%d",&type[i],&x[i]);

        if(type[i]!=2)
            scanf("%d",&y[i]);

        if(type[i]==1)
            v[y[i]].push_back(x[i]);
    }

    for(int i=1;i<=n;i++)
        if(in[i]==0 && v[i].size()>0)
            dfs(i,0);

    int cnt_packet=0;
    for(int i=1;i<=m;i++){

        if(type[i]==1)
            connect(x[i],y[i]);

        else if(type[i]==2)
            cnt_packet++,em[cnt_packet]=x[i];

        else
            cout<<( root(x[i])==root(em[y[i]] ) && in[x[i]]<=in[em[y[i]]] && out[x[i]]>=out[em[y[i]]] ?"YES":"NO"  )<<endl;

    }
}


#include <bits/stdc++.h>
using namespace std;
const int inf=1e5+9;
int n,m,type[inf],x[inf],y[inf],in[inf],out[inf],timer=1,par[inf],sz[inf],deg[inf],ans[inf];
vector<int> v[inf];
vector<pair<int,int> > packet[inf];

void dfs(int node,int par){

    in[node]=timer++;
    for(auto o:v[node])
        if(o!=par && in[o]==0)
            dfs(o,node);

    out[node]=timer++;
}

int root(int x){

    if(x==par[x])
        return x;

    return par[x]=root(par[x]);
}

void connect(int x,int y){

    x=root(x),y=root(y);
    if(x==y)
        return ;

    if(sz[x]>sz[y])
        swap(x,y);

    par[x]=y;
    sz[y]+=sz[x];
}

bool parent(int a,int b){

    return (in[a]<=in[b] && out[a]>=out[b]);
}

int main(){

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        par[i]=i,sz[i]=1;

    for(int i=1;i<=m;i++){

        scanf("%d%d",&type[i],&x[i]);

        if(type[i]!=2)
            scanf("%d",&y[i]);

        if(type[i]==1)
            v[y[i]].push_back(x[i]),deg[x[i]]++;

        if(type[i]==3)
            packet[y[i]].push_back(make_pair(i, x[i] ));
    }

    for(int i=1;i<=n;i++)
        if(in[i]==0 && deg[i]==0)
            dfs(i,0);

    int cnt_packet=0;
    for(int i=1;i<=m;i++){

        if(type[i]==1)
            connect(x[i],y[i]);

        if(type[i]!=2)
            continue;

        cnt_packet++;
        for(auto o:packet[cnt_packet]  )
            ans[o.first]=(root(x[i])==root(o.second) && parent(o.second,x[i])  );
    }

    for(int i=1;i<=m;i++)
        if(type[i]==3)
            cout<<(ans[i]?"YES":"NO")<<endl;
}


#include <bits/stdc++.h>
using namespace std;
const int inf=1e5+9;
int n,m,type[inf],x[inf],y[inf],in[inf],out[inf],timer=1,par[inf],em[inf],sz[inf];
vector<int> v[inf];
vector<pair<int,int> > ans;

void dfs(int node,int par){

    in[node]=timer++;
    for(auto o:v[node])
        if(o!=par)
            dfs(o,node);

    out[node]=timer-1;
}

int root(int x){

    if(x==par[x])
        return x;
    return par[x]=root(par[x]);
}

void connect(int x,int y){

    x=root(x),y=root(y);
    if(x==y)
        return ;
    if(sz[x]>sz[y])
        swap(x,y);

    par[x]=y;
    sz[y]+=sz[x];
}

int main(){

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        par[i]=i,sz[i]=1;

    for(int i=1;i<=m;i++){

        scanf("%d%d",&type[i],&x[i]);

        if(type[i]!=2)
            scanf("%d",&y[i]);

        if(type[i]==1)
            v[y[i]].push_back(x[i]);
    }

    for(int i=1;i<=n;i++)
        if(in[i]==0 && v[i].size()>0)
            dfs(i,0);

    int cnt_packet=0;
    for(int i=1;i<=m;i++){

        if(type[i]==1)
            connect(x[i],y[i]);

        else if(type[i]==2)
            cnt_packet++,em[cnt_packet]=x[i];

        else{
            if( root(x[i])==root(em[y[i]] ) && in[x[i]]<=in[em[y[i]]] && out[x[i]]>=out[em[y[i]]])
                printf("YES\n");
            else
                printf("NO\n");
        }

    }
}


#include <bits/stdc++.h>
using namespace std;
const int inf=1e5+9;
int n,m,type[inf],x[inf],y[inf],in[inf],out[inf],timer=1,par[inf],em[inf],sz[inf],deg[inf];
vector<int> v[inf];
vector<pair<int,int> > ans;

void dfs(int node,int par){

    in[node]=timer++;
    for(auto o:v[node])
        if(o!=par && in[o]==0)
            dfs(o,node);

    out[node]=timer++;
}

int root(int x){

    if(x==par[x])
        return x;

    return par[x]=root(par[x]);
}

void connect(int x,int y){

    x=root(x),y=root(y);
    if(x==y)
        return ;

    if(sz[x]>sz[y])
        swap(x,y);

    par[x]=y;
    sz[y]+=sz[x];
}

int main(){

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        par[i]=i,sz[i]=1;

    for(int i=1;i<=m;i++){

        scanf("%d%d",&type[i],&x[i]);

        if(type[i]!=2)
            scanf("%d",&y[i]);

        if(type[i]==1)
            v[y[i]].push_back(x[i]),deg[x[i]]++;
    }

    for(int i=1;i<=n;i++)
        if(in[i]==0 &&deg[i]==0)
            dfs(i,0);

    int cnt_packet=0;
    for(int i=1;i<=m;i++){

        if(type[i]==1)
            connect(x[i],y[i]);

        else if(type[i]==2)
            cnt_packet++,em[cnt_packet]=x[i];

        else{
            if( root(x[i])==root(em[y[i]] ) && in[x[i]]<=in[em[y[i]]] && out[x[i]]>=out[em[y[i]]])
                printf("YES\n");
            else
                printf("NO\n");
        }

    }
}


#include <bits/stdc++.h>
using namespace std;
const int inf=1e5+9;
int n,m,type[inf],x[inf],y[inf],in[inf],out[inf],timer=1,par[inf],em[inf],sz[inf];
vector<int> v[inf];
vector<pair<int,int> > ans;

void dfs(int node,int par){

    in[node]=timer++;
    for(auto o:v[node])
        if(o!=par && in[o]==0)
            dfs(o,node);

    out[node]=timer-1;
}

int root(int x){

    if(x==par[x])
        return x;

    return par[x]=root(par[x]);
}

void connect(int x,int y){

    x=root(x),y=root(y);
    if(x==y)
        return ;

    if(sz[x]>sz[y])
        swap(x,y);

    par[x]=y;
    sz[y]+=sz[x];
}

int main(){

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        par[i]=i,sz[i]=1;

    for(int i=1;i<=m;i++){

        scanf("%d%d",&type[i],&x[i]);

        if(type[i]!=2)
            scanf("%d",&y[i]);

        if(type[i]==1)
            v[y[i]].push_back(x[i]);
    }

    for(int i=1;i<=n;i++)
        if(in[i]==0 && v[i].size()>0)
            dfs(i,0);

    int cnt_packet=0;
    for(int i=1;i<=m;i++){

        if(type[i]==1)
            connect(x[i],y[i]);

        else if(type[i]==2)
            cnt_packet++,em[cnt_packet]=x[i];

        else{
            if( root(x[i])==root(em[y[i]] ) && in[x[i]]<=in[em[y[i]]] && out[x[i]]>=out[em[y[i]]])
                printf("YES\n");
            else
                printf("NO\n");
        }

    }
}


#include <iostream>
#include <vector>
using namespace std;
const int N = 100000 + 10;

int n,m,t,par[N],T;
vector<int> g[N];
int find(int x){
    return par[x]==x?x:par[x]=find(par[x]);
}
pair<int,int> p[N];
struct Q {
    int t,x,y;
    void read() {
        scanf("%d",&t);
        if(t==1){
            scanf("%d%d",&x,&y); g[y].push_back(x);
            par[find(x)]=find(y);
        }
        if(t==2){
            scanf("%d",&x);
            p[++T] = make_pair(x,find(x));
        }
        if(t==3){
            scanf("%d%d",&x,&y);
        }

    }
} q[N];

int fa[N][20],dep[N];
void dfs(int u,int p) {
    fa[u][0]=p,dep[u]=dep[p]+1;
    for(auto v: g[u]) {
        if(v==p) continue;
        //printf("%d->%d\n", u,v);
        dfs(v,u);
    }
}

int lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    int d=dep[u]-dep[v];

    for(int i=19;i>=0;i--)if(d>>i&1)u=fa[u][i];
    if(u==v){
        return u;
    }
    for(int i=19;i>=0;i--) {
        if(fa[u][i]!=fa[v][i]){
            u=fa[u][i],v=fa[v][i];
        }
    }
    return fa[u][0];
}
bool vis[N];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) par[i]=i;
    for(int i=1;i<=m;i++) {
        q[i].read();
    }
    for(int i=1;i<=n;i++){
        if(vis[find(i)] == 0){
            dfs(find(i),find(i));vis[find(i)]=1;
        }
    }
    for(int i=1;i<20;i++) for(int j=1;j<=n;j++) fa[j][i]=fa[fa[j][i-1]][i-1];
    //printf("lca %d\n", lca(3,4)); return 0;
    for(int i=1;i<=m;i++) {
        if(q[i].t == 3) {
            int u = p[q[i].y].second;
            int v = p[q[i].y].first;
            //printf("%d - %d %d\n", u,v, q[i].x);
            if (lca(q[i].x, v) == q[i].x && lca(q[i].x, u) == u)
                printf("YES\n");
            else
                printf("NO\n");
        }
    }
}


#include <iostream>
#include <vector>
using namespace std;
const int N = 100000 + 10;

int n,m,t,par[N],T;
vector<int> g[N];
int find(int x){
    return par[x]==x?x:par[x]=find(par[x]);
}
pair<int,int> p[N];
struct Q {
    int t,x,y;
    void read() {
        scanf("%d",&t);
        if(t==1){
            scanf("%d%d",&x,&y); g[y].push_back(x);
            par[find(x)]=find(y);
        }
        if(t==2){
            scanf("%d",&x);
            p[++T] = make_pair(x,find(x));
        }
        if(t==3){
            scanf("%d%d",&x,&y);
        }

    }
} q[N];

int fa[N][20],dep[N];
void dfs(int u,int p) {
    fa[u][0]=p,dep[u]=dep[p]+1;
    for(auto v: g[u]) {
        if(v==p) continue;
        //printf("%d->%d\n", u,v);
        dfs(v,u);
    }
}

int lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    int d=dep[u]-dep[v];

    for(int i=19;i>=0;i--)if(d>>i&1)u=fa[u][i];
    if(u==v){
        return u;
    }
    for(int i=19;i>=0;i--) {
        if(fa[u][i]!=fa[v][i]){
            u=fa[u][i],v=fa[v][i];
        }
    }
    return fa[u][0];
}
bool vis[N];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) par[i]=i;
    for(int i=1;i<=m;i++) {
        q[i].read();
    }
    for(int i=1;i<=n;i++){
        if(vis[find(i)] == 0)
        dfs(find(i),find(i));
    }
    for(int i=1;i<20;i++) for(int j=1;j<=n;j++) fa[j][i]=fa[fa[j][i-1]][i-1];
    //printf("lca %d\n", lca(3,4)); return 0;
    for(int i=1;i<=m;i++) {
        if(q[i].t == 3) {
            int u = p[q[i].y].second;
            int v = p[q[i].y].first;
            //printf("%d - %d %d\n", u,v, q[i].x);
            if (lca(q[i].x, v) == q[i].x && lca(q[i].x, u) == u)
                printf("YES\n");
            else
                printf("NO\n");
        }
    }
}


#include <iostream>
#include <vector>
using namespace std;
const int N = 100000 + 10;

int n,m,t,par[N],T;
vector<int> g[N];
int find(int x){
    return par[x]==x?x:par[x]=find(par[x]);
}
pair<int,int> p[N];
struct Q {
    int t,x,y;
    void read() {
        scanf("%d",&t);
        if(t==1){
            scanf("%d%d",&x,&y); g[y].push_back(x);
            par[find(x)]=find(y);
        }
        if(t==2){
            scanf("%d",&x);
            p[++T] = make_pair(x,find(x));
        }
        if(t==3){
            scanf("%d%d",&x,&y);
        }

    }
} q[N];

int fa[N][20],dep[N];
void dfs(int u,int p) {
    fa[u][0]=p,dep[u]=dep[p]+1;
    for(auto v: g[u]) {
        if(v==p) continue;
        //printf("%d->%d\n", u,v);
        dfs(v,u);
    }
}

int lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    int d=dep[u]-dep[v];

    for(int i=19;i>=0;i--)if(d>>i&1)u=fa[u][i];
    if(u==v){
        return u;
    }
    for(int i=19;i>=0;i--) {
        if(fa[u][i]!=fa[v][i]){
            u=fa[u][i],v=fa[v][i];
        }
    }
    return fa[u][0];
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) par[i]=i;
    for(int i=1;i<=m;i++) {
        q[i].read();
    }
    dfs(find(1),find(1));
    for(int i=1;i<20;i++) for(int j=1;j<=n;j++) fa[j][i]=fa[fa[j][i-1]][i-1];
    //printf("lca %d\n", lca(3,4)); return 0;
    for(int i=1;i<=m;i++) {
        if(q[i].t == 3) {
            int u = p[q[i].y].second;
            int v = p[q[i].y].first;
            //printf("%d - %d %d\n", u,v, q[i].x);
            if (lca(q[i].x, v) == q[i].x && lca(q[i].x, u) == u)
                printf("YES\n");
            else
                printf("NO\n");
        }
    }
}


#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, m;
const int N = 1e5 + 5;
int par[N], in[N], out[N], rev[N], vis[N], tim = 0, idd = 1, date[N];
vector<pair<int, int> > vec;
vector<vector<pair<int, int> > > g(N);
vector<pair<int, int> > sor[N];
void dfs(int node)
{
	vis[node] = idd;
	in[node] = ++tim;
	for (int i = 0; i < g[node].size(); i++)
		dfs(g[node][i].first);
	for (int i = 0; i < g[node].size(); i++)
		sor[node].push_back(make_pair(in[g[node][i].first], g[node][i].second));
	out[node] = tim;
}
bool isansector(int u, int v)
{
	return in[u] <= in[v] && out[u] >= out[v];
}
vector<pair<int, int> >::iterator it;
bool check(int u, int v, int t)
{
	it = upper_bound(sor[u].begin(), sor[u].end(), make_pair(in[v], N));
	it--;
	return it->second <= t;
}
int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		par[i] = -1;
	int id = 0;
	for (int i = 0; i < m; i++)
	{
		int t;
		cin >> t;
		if (t == 1)
		{
			int u, v;
			cin >> u >> v;
			par[u] = v;
			g[v].push_back(make_pair(u, i));
		}
		else if (t == 2)
		{
			int x;
			cin >> x;
			id++;
			rev[id] = x;
			date[id] = i;
		}
		else
		{
			int u, x;
			cin >> u >> x;
			vec.push_back(make_pair(u, x));
		}
	}
	for (int i = 1; i <= n; i++)
		if (par[i] == -1)
		{
			dfs(i);
			idd++;
			tim = 0;
		}
	for (int i = 0; i < vec.size(); i++)
	{
		int u = vec[i].first, v = rev[vec[i].second];
		if (vis[u] != vis[v] || isansector(u, v) == 0)
			cout << "NO" << '\n';
		else
		{
			if (check(u, v, date[vec[i].second]))
				cout << "YES" << '\n';
			else
				cout << "NO" << '\n';
		}

	}
	return 0;
}


#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, m;
const int N = 1e5 + 5;
int par[N], in[N], out[N], rev[N], vis[N], tim = 0, idd = 1, date[N];
vector<pair<int, int> > vec;
vector<vector<pair<int, int> > > g(N);
int pth[N][20], sp[N][20], lvl[N];
void build()
{
	for (int i = 1; i <= 18; i++)
		for (int j = 1; j <= n; j++)
		{
			pth[j][i] = pth[pth[j][i - 1]][i - 1];
			sp[j][i] = max(sp[j][i - 1], sp[pth[j][i - 1]][i - 1]);
		}
}
int get(int u, int v)
{
	int l = lvl[u] - lvl[v];
	int ma = 0;
	for (int i = 18; i >= 0; i--)
		if (l & (1 << i))
			ma = max(ma, sp[u][i]), u = pth[u][i];
	return ma;
}

void dfs(int node, int pa, int temp, int l)
{
	lvl[node] = l;
	vis[node] = idd;
	in[node] = ++tim;
	pth[node][0] = pa;
	sp[node][0] = temp;
	for (int i = 0; i < g[node].size(); i++)
		dfs(g[node][i].first, node, g[node][i].second, l + 1);
	out[node] = tim;
}
bool isansector(int u, int v)
{
	return in[u] <= in[v] && out[u] >= out[v];
}
bool check(int u, int v, int t)
{
	return get(v, u) <= t;
}
int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		par[i] = -1;
	int id = 0;
	for (int i = 0; i < m; i++)
	{
		int t;
		cin >> t;
		if (t == 1)
		{
			int u, v;
			cin >> u >> v;
			par[u] = v;
			g[v].push_back(make_pair(u, i));
		}
		else if (t == 2)
		{
			int x;
			cin >> x;
			id++;
			rev[id] = x;
			date[id] = i;
		}
		else
		{
			int u, x;
			cin >> u >> x;
			vec.push_back(make_pair(u, x));
		}
	}
	for (int i = 1; i <= n; i++)
		if (par[i] == -1)
		{
			dfs(i, i, 0, 0);
			idd++;
			tim = 0;
		}

	build();
	for (int i = 0; i < vec.size(); i++)
	{
		int u = vec[i].first, v = rev[vec[i].second];
		if (vis[u] != vis[v] || isansector(u, v) == 0)
			cout << "NO" << '\n';
		else
		{
			if (u == v || check(u, v, date[vec[i].second]))
				cout << "YES" << '\n';
			else
				cout << "NO" << '\n';
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, m;
const int N = 1e5 + 5;
int par[N], in[N], out[N], rev[N], vis[N], tim = 0, idd = 1, date[N];
vector<pair<int, int> > vec;
vector<vector<pair<int, int> > > g(N);
vector<pair<int, int> > sor[N];
void dfs(int node)
{
	vis[node] = idd;
	in[node] = ++tim;
	for (int i = 0; i < g[node].size(); i++)
		dfs(g[node][i].first);
	for (int i = 0; i < g[node].size(); i++)
		sor[node].push_back(make_pair(in[g[node][i].first], g[node][i].second));
	out[node] = tim;
}
bool isansector(int u, int v)
{
	return in[u] <= in[v] && out[u] >= out[v];
}
vector<pair<int, int> >::iterator it;
bool check(int u, int v, int t)
{
	int s = 0, e = sor[u].size() - 1, ans = 1e8;
	while (s <= e)
	{
		int mid = (s + e) >> 1;
		if (sor[u][mid].first <= in[v])
			s = mid + 1, ans = sor[u][mid].second;
		else
			e = mid - 1;
	}
	return ans <= t;
}
int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		par[i] = -1;
	int id = 0;
	for (int i = 0; i < m; i++)
	{
		int t;
		cin >> t;
		if (t == 1)
		{
			int u, v;
			cin >> u >> v;
			par[u] = v;
			g[v].push_back(make_pair(u, i));
		}
		else if (t == 2)
		{
			int x;
			cin >> x;
			id++;
			rev[id] = x;
			date[id] = i;
		}
		else
		{
			int u, x;
			cin >> u >> x;
			vec.push_back(make_pair(u, x));
		}
	}
	for (int i = 1; i <= n; i++)
		if (par[i] == -1)
		{
			dfs(i);
			idd++;
			tim = 0;
		}
	for (int i = 0; i < vec.size(); i++)
	{
		int u = vec[i].first, v = rev[vec[i].second];
		if (vis[u] != vis[v] || isansector(u, v) == 0)
			cout << "NO" << '\n';
		else
		{
			if (u == v || check(u, v, date[vec[i].second]))
				cout << "YES" << '\n';
			else
				cout << "NO" << '\n';
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, m;
const int N = 1e5 + 5;
int par[N], in[N], out[N], rev[N], vis[N], tim = 0, idd = 1, date[N];
vector<pair<int, int> > vec;
vector<vector<pair<int, int> > > g(N);
vector<pair<int, int> > sor[N];
void dfs(int node)
{
	vis[node] = idd;
	in[node] = ++tim;
	for (int i = 0; i < g[node].size(); i++)
		dfs(g[node][i].first);
	for (int i = 0; i < g[node].size(); i++)
		sor[node].push_back(make_pair(in[g[node][i].first], g[node][i].second));
	out[node] = tim;
}
bool isansector(int u, int v)
{
	return in[u] <= in[v] && out[u] >= out[v];
}
vector<pair<int, int> >::iterator it;
bool check(int u, int v, int t)
{
	int s = 0, e = sor[u].size() - 1, ans = 1e8;
	while (s <= e)
	{
		int mid = (s + e) >> 1;
		if (sor[u][mid].first <= in[v])
			s = mid + 1, ans = sor[u][mid].second;
		else
			e = mid - 1;
	}
	return ans <= t;
}
int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		par[i] = -1;
	int id = 0;
	for (int i = 0; i < m; i++)
	{
		int t;
		cin >> t;
		if (t == 1)
		{
			int u, v;
			cin >> u >> v;
			par[u] = v;
			g[v].push_back(make_pair(u, i));
		}
		else if (t == 2)
		{
			int x;
			cin >> x;
			id++;
			rev[id] = x;
			date[id] = i;
		}
		else
		{
			int u, x;
			cin >> u >> x;
			vec.push_back(make_pair(u, x));
		}
	}
	for (int i = 1; i <= n; i++)
		if (par[i] == -1)
		{
			dfs(i);
			idd++;
			tim = 0;
		}
	for (int i = 0; i < vec.size(); i++)
	{
		int u = vec[i].first, v = rev[vec[i].second];
		if (vis[u] != vis[v] || isansector(u, v) == 0)
			cout << "NO" << '\n';
		else
		{
			if (check(u, v, date[vec[i].second]))
				cout << "YES" << '\n';
			else
				cout << "NO" << '\n';
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define nmax 100005

using namespace std;

struct query{
	int t;
	int x,y,ind;
};

vector<vector<int>> g;
int p[nmax]={},st[nmax],en[nmax],par[nmax];
pair<int,int> let[nmax];
vector<query> q[nmax];
string ans[nmax];
int tt=0;

void dfs(int u){
	st[u]=tt++;
	for(auto v:g[u]){
		dfs(v);
	}
	en[u]=tt;
}

int root(int u){
	if(par[u]==u){
		return u;
	}
	return par[u]=root(par[u]);
}

void merge(int u, int v){
	if(rand()%2){
		swap(u,v);
	}
	par[root(v)]=root(u);
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m; cin >> n >> m;
	vector<query> a(m);
	g.resize(n+1);

	for(int i=0;i<m;i++){
		cin >> a[i].t;
		if(a[i].t==1){
			cin >> a[i].x >> a[i].y;
			g[a[i].y].push_back(a[i].x);
			p[a[i].x]=a[i].y;
		}
		else if(a[i].t==2){
			cin >> a[i].x;
		}
		else{
			cin >> a[i].x >> a[i].ind;
		}
	}

	for(int i=1;i<=n;i++){
		if(!p[i]){
			dfs(i);
		}
	}
	int cl=1;
	for(int i=0;i<m;i++){
		if(a[i].t==2){
			let[cl++]={a[i].x,i};
		}
		else if(a[i].t==3){
			int lind=let[a[i].ind].second;
			q[lind].push_back({0,let[a[i].ind].first,a[i].x,i});
		}
	}

	iota(par+1,par+n+1,1);
	for(int i=0;i<m;i++){
		if(a[i].t==1){
			merge(a[i].x,a[i].y);
		}
		else if(a[i].t==2){
			for(auto cur:q[i]){
				if((st[cur.y]<=st[cur.x] && en[cur.y]>=en[cur.x])&&
						(root(cur.y)==root(cur.x))){
					ans[cur.ind]="YES";
				}
				else{
					ans[cur.ind]="NO";
				}
			}
		}
	}
	for(int i=0;i<m;i++){
		if(a[i].t==3){
			cout << ans[i] << endl;
		}
	}

	return 0;
}


#include <bits/stdc++.h>
#define nmax 100005

using namespace std;

struct query{
	int t;
	int x,y,ind;
};

vector<vector<int>> g;
int p[nmax]={},st[nmax],en[nmax],let[nmax],par[nmax];
int tt=0;

void dfs(int u){
	st[u]=tt++;
	for(auto v:g[u]){
		dfs(v);
	}
	en[u]=tt;
}

int root(int u){
	if(par[u]==u){
		return u;
	}
	return par[u]=root(par[u]);
}

void merge(int u, int v){
	if(rand()%2){
		swap(u,v);
	}
	par[root(v)]=root(u);
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m; cin >> n >> m;
	vector<query> a(m);
	g.resize(n+1);

	for(int i=0;i<m;i++){
		cin >> a[i].t;
		if(a[i].t==1){
			cin >> a[i].x >> a[i].y;
			g[a[i].y].push_back(a[i].x);
			p[a[i].x]=a[i].y;
		}
		else if(a[i].t==2){
			cin >> a[i].x;
		}
		else{
			cin >> a[i].x >> a[i].ind;
		}
	}

	for(int i=1;i<=n;i++){
		if(!p[i]){
			dfs(i);
		}
	}

	iota(par+1,par+n+1,1);
	int cl=1;
	for(int i=0;i<m;i++){
		if(a[i].t==1){
			merge(a[i].x,a[i].y);
		}
		else if(a[i].t==2){
			let[cl++]=a[i].x;
		}
		else{
			int y=a[i].x,x=let[a[i].ind];
			if((st[y]<=st[x] && en[y]>=en[x])&&
					(root(y)==root(x))){
				cout << "YES" << endl;
			}
			else{
				cout << "NO" << endl;
			}
		}
	}
	return 0;
}


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

#define inf 1000000000
#define inf_ll 1000000000000000000ll
#define inf_ull 1000000000000000000ull
#define ll long long
#define ull unsigned long long
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define pb push_back

#ifdef ONLINE_JUDGE
#define debug(...)
#define fin cin
#else
#include "../../debug.cpp"
#endif

// both unite and query take effectively constant time
struct unionfind {

    int length;
    vector<int> parent;

    unionfind(int s) {
        length = s;
        parent.assign(s, 0);
        std::iota(parent.begin(), parent.end(), 0);
    }

    int rep(int x) {
        while (x != parent[x]) {
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }

    void unite(int a, int b) {
        a = rep(a);
        b = rep(b);
        if (a == b)
            return;
        parent[b] = a;
    }

    // returns true if a and b are in the same set.
    inline bool query(int a, int b) {
        return rep(a) == rep(b);
    }
};

// O(nlogn) to set up, O(1) to query
struct lca {

    vector<pair<int, int>> euler_walk;
    vector<vector<pair<int, int>>> range_mins;
    vector<int> walk_index;
    vector<bool> visited;

    void _label_walk(vector<vector<int>>& edges, int i, int depth) {
        visited[i] = 1;
        walk_index[i] = euler_walk.size();
        euler_walk.push_back({depth, i});
        for (int j : edges[i]) {
            if (visited[j]) continue;
            _label_walk(edges, j, depth+1);
            euler_walk.push_back({depth, i});
        }
    }

    // Accepts an adjecency list. Can include or exlude parents, it works either way.
    lca(vector<vector<int>>& edges, int root) {

        // set up the euler walk
        walk_index.assign(edges.size(), 0);
        visited.assign(edges.size(), 0);
        _label_walk(edges, root, 0);

        // set up RMQ lookup table
        range_mins.push_back({});
        for (int i = 0; i < euler_walk.size(); i++)
            range_mins.back().push_back(euler_walk[i]);
        for (int len = 2; len <= euler_walk.size(); len <<= 1) {
            auto prev = range_mins.back();
            range_mins.push_back({});
            for (int i = 0; i < euler_walk.size()-len+1; i++)
                range_mins.back().push_back(min(prev[i], prev[i+len/2]));
        }
    }

    int query(int i, int j) {
        int a = min(walk_index[i], walk_index[j]);
        int b = max(walk_index[i], walk_index[j]);
        if (b == a) return i;
        int n = floor(log2(b-a));
        return min(range_mins[n][a], range_mins[n][b-pow(2, n)+1]).second;
    }
};

int main() {
    ios_base::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
    int n, m; fin >> n >> m;
    int c = 1, e, r = -1;

    vector<array<int, 5>> ev(m);
    vector<int> res(m, -1), deg(n+1, 0);
    vector<vector<int>> adj(n+1);

    for (int i = 0; i < m; i++) {
        fin >> ev[i][4];
        ev[i][0] = c; ev[i][1] = i;
        if (ev[i][4] == 1) {
            fin >> ev[i][2] >> ev[i][3];
            adj[ev[i][3]].pb(ev[i][2]);
            deg[ev[i][2]]++;
        }
        if (ev[i][4] == 2) {
            c++; fin >> ev[i][2];
        }
        if (ev[i][4] == 3)
            fin >> ev[i][2] >> ev[i][0];
    }

    for (int i = 0; i < n; i++)
        if (deg[i] == 0)
            adj[0].pb(i);

    unionfind u(n+1);
    lca l(adj, 0);
    sort(all(ev));

    for (auto& [_, i, x, y, t] : ev) {
        if (t == 1)
            u.unite(x, y);
        if (t == 2)
            e = x;
        if (t == 3)
            res[i] = u.query(e, x) && (l.query(e, x) == x);
    }

    for (auto& x : res)
        if (x != -1)
            cout << (x ? "YES" : "NO") << "\n";
}


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

#define inf 1000000000
#define inf_ll 1000000000000000000ll
#define inf_ull 1000000000000000000ull
#define ll long long
#define ull unsigned long long
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define pb push_back

#ifdef ONLINE_JUDGE
#define debug(...)
#define fin cin
#else
#include "../../debug.cpp"
#endif

// both unite and query take effectively constant time
struct unionfind {

    int length;
    vector<int> parent;

    unionfind(int s) {
        length = s;
        parent.assign(s, 0);
        std::iota(parent.begin(), parent.end(), 0);
    }

    int rep(int x) {
        while (x != parent[x]) {
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }

    void unite(int a, int b) {
        a = rep(a);
        b = rep(b);
        if (a == b)
            return;
        parent[b] = a;
    }

    // returns true if a and b are in the same set.
    inline bool query(int a, int b) {
        return rep(a) == rep(b);
    }
};

struct ktha {

    vector<vector<int>> parent;
    vector<bool> visited;

    void _label_parent(int i, vector<vector<int>>& adj) {
        visited[i] = 1;
        for (int j : adj[i])
            if (!visited[j]) {
                parent[0][j] = i;
                _label_parent(j, adj);
            }
    }

    // Accepts an adjecency list. Can include or exlude parents, it works either way.
    ktha(vector<vector<int>>& adj, int root) {

        int maxexp = floor(log2(adj.size()));
        parent.assign(maxexp+1, vector<int>(adj.size()));
        visited.assign(adj.size(), 0);

        _label_parent(root, adj);
        for (int exp = 1; exp <= maxexp; exp++)
            for (int i = 0; i < adj.size(); i++)
                parent[exp][i] = parent[exp-1][parent[exp-1][i]];
    }

    // Returns the k-th ancestor of node i.
    int query(int i, int k) {
        for (int j = 0; (1<<j) <= k; j++)
            if (k&(1<<j))
                i = parent[j][i];
        return i;
    }
};

int main() {
    ios_base::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
    int n, m; fin >> n >> m;
    int c = 1, e, r = -1;

    vector<array<int, 5>> ev(m);
    vector<int> res(m, -1), deg(n+1, 0), depth(n+1, 0);
    vector<vector<int>> adj(n+1);

    for (int i = 0; i < m; i++) {
        fin >> ev[i][4];
        ev[i][0] = c; ev[i][1] = i;
        if (ev[i][4] == 1) {
            fin >> ev[i][2] >> ev[i][3];
            adj[ev[i][3]].pb(ev[i][2]);
            deg[ev[i][2]]++;
        }
        if (ev[i][4] == 2) {
            c++; fin >> ev[i][2];
        }
        if (ev[i][4] == 3)
            fin >> ev[i][2] >> ev[i][0];
    }

    for (int i = 1; i <= n; i++)
        if (deg[i] == 0)
            adj[0].pb(i);

    unionfind u(n+1);
    ktha k(adj, 0);

    vector<int> stack = {0};
    while (!stack.empty()) {
        int i = stack.back(); stack.pop_back();
        for (int j : adj[i]) {
            depth[j] = depth[i]+1;
            stack.pb(j);
        }
    }

    sort(all(ev));
    for (auto& [_, i, x, y, t] : ev) {
        if (t == 1)
            u.unite(x, y);
        if (t == 2)
            e = x;
        if (t == 3) {
            res[i] = u.query(e, x) && (k.query(e, depth[e]-depth[x]) == x);
        }
    }

    for (auto& x : res)
        if (x != -1)
            cout << (x ? "YES" : "NO") << "\n";
}


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

#define pb push_back

const int maxn=100005;

int n,m,stt=0;
int caygoc[maxn], fa[maxn];
vector<int> v1,v2;

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

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<=n;i++) caygoc[i] = fa[i] = i;
	int c,a,b;
	while(m--)
	{
		scanf("%d",&c);
		if(c==1)
		{
			scanf("%d%d",&a,&b);
			fa[a] = b; caygoc[a] = b;
		}
		else if(c==2)
		{
			scanf("%d",&a);
			v1.pb(a);
			v2.pb(find(a));
		}
		else if(c==3)
		{
			scanf("%d%d",&a,&b);
			b--;
			int child = v1[b], root = v2[b];
			bool flag = false;
			while (1) {
				if (child == a) {
					flag =true;
					break;
				}
				if (child == root) break;
				child = caygoc[child];
			}
			if (flag) cout << "YES\n";
			else cout << "NO";
		}
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int maxn=100100;

int n,m;
int fa[maxn],bef[maxn];
vector<int> v1,v2;

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

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<=n+10;i++) fa[i]=bef[i]=i;
	int c,a,b;
	while(m--)
	{
		scanf("%d",&c);
		if(c==1)
		{
			scanf("%d%d",&a,&b);
			bef[a]=b; fa[a]=b;
		}
		else if(c==2)
		{
			scanf("%d",&a);
			v1.push_back(a);
			v2.push_back(find(a));
		}
		else if(c==3)
		{
			scanf("%d%d",&a,&b);
			b--;
			int son=v1[b],father=v2[b];
			bool flag=false;
			while(true)
			{
				if(son==a)
				{
					flag=true;
					break;
				}
				if(son==father) break;
				son=bef[son];
			}
			if(flag) puts("YES");
			else puts("NO");
		}
	}
	return 0;
}


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

#define pb push_back

const int maxn=100005;

int n,m,stt=0;
int caygoc[maxn], fa[maxn];
vector<int> v1,v2;

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

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<=n;i++) caygoc[i] = fa[i] = i;
	int c,a,b;
	while(m--)
	{
		scanf("%d",&c);
		if(c==1)
		{
			scanf("%d%d",&a,&b);
			fa[a] = b; caygoc[a] = b;
		}
		else if(c==2)
		{
			scanf("%d",&a);
			v1.pb(a);
			v2.pb(find(a));
		}
		else if(c==3)
		{
			scanf("%d%d",&a,&b);
			b--;
			int child = v1[b], root = v2[b];
			bool flag = false;
			while (1) {
				if (child == a) {
					flag =true;
					break;
				}
				if (child == root) break;
				child = caygoc[child];
			}
			if (flag) cout << "YES\n";
			else cout << "NO\n";
		}
	}
	return 0;
}


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

#define pb push_back

typedef long long li;

int n, m, no = 0;
vector <vector<int> > dsk;
vector <bool> chosen;
vector <vector<int> > sign;

void bfs(int a) {
	queue <int> q;
	q.push(a);
	//chosen[a] = true;

	while (!q.empty()) {
		int u = q.front(); q.pop();
		chosen[u] = true;
		sign[u].pb(no);
		for (int i=0; i<(int)dsk[u].size(); i++) {
			int v = dsk[u][i];
			if (chosen[v] == false) {
				q.push(v);
				//chosen[v] = true;
			}
		}
	}
}

void dfs(int u) {
	chosen[u] = true;
	sign[u].pb(no);
	for (int i=0; i<(int)dsk[u].size(); i++) {
		int v = dsk[u][i];
		if (!chosen[v]) dfs(v);
	}
}

bool search(int x, int st, int en, int val) {
	if (st > en) return false;
	int mid = (st+en) / 2;
	if (sign[x][mid] == val) return true;
	if (sign[x][mid] < val) return search(x, mid+1, en, val);
	return search(x, st, mid-1, val);
}

int main() {
	cin >> n >> m;
	dsk.resize(n+1);
	sign.resize(n+1);
	while (m--) {
		int loai; cin >> loai;
		if (loai == 1) {
			int a, b; cin >> a >> b;
			dsk[a].pb(b);
		}
		else if (loai == 2) {
			no++;
			int a; cin >> a;
			chosen.assign(n+1, false);
			bfs(a);
		}
		else { // loai == 3
			//for (int i=1; i<=n; i++) sort(sign[i].begin(), sign[i].end());
			int x, g; cin >> x >> g;
			if (search(x, 0, sign[x].size()-1, g)) cout << "YES\n";
			else cout << "NO\n";
		}
	}
	return 0;
}


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

#define pb push_back

const int maxn=100005;

int n,m,stt=0;
int father[maxn];
vector <vector<int> > ky;

void dien(int a) {
	while (a != father[a]) {
		ky[a].pb(stt);
		a = father[a];
	}
	ky[a].pb(stt);
}

bool search(int x, int st, int en, int val) {
	if (st > en) return false;
	int mid = (st+en) / 2;
	if (ky[x][mid] == val) return true;
	if (ky[x][mid] < val) return search(x, mid+1, en, val);
	return search(x, st, mid-1, val);
}

int main()
{
	scanf("%d%d",&n,&m);
	ky.resize(n+1);
	for(int i=0;i<=n;i++) father[i] = i;
	int c,a,b;
	while(m--)
	{
		scanf("%d",&c);
		if(c==1)
		{
			scanf("%d%d",&a,&b);
			father[a] = b;
		}
		else if(c==2)
		{
			stt++;
			scanf("%d",&a);
			dien(a);
		}
		else if(c==3)
		{
			scanf("%d%d",&a,&b);
			if (search(a, 0, ky[a].size()-1, b)) cout << "YES\n";
			else cout << "NO\n";
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX = 1e5 + 10;

vector<vector<int>> adjList(MAX);
vector<int> tin(MAX, 0), tout(MAX, 0);

int timer = 0;

void TopologicalSort (int nd, vector<int>& tops) {
  tin[nd] = 1;
  for (int nxt : adjList[nd]) {
    if (!tin[nd])
      TopologicalSort(nxt, tops);
  }
  tops.push_back(nd);
}

void dfs (int nd) {
  tin[nd] = timer++;
  for (int nxt : adjList[nd]) {
    dfs(nxt);
  }
  tout[nd] = timer++;
}

class Dsu {
public:
  int n;
  vector<int> p, rnk;

  Dsu (int _n) : n(_n) {
    p = rnk = vector<int> (n, 0);
    iota(p.begin(), p.end(), 0);
  }

  int getPar (int x) {
    return p[x] == x ? x : (p[x] = getPar(p[x]));
  }

  void unite (int a, int b) {
    int x = getPar(a), y = getPar(b);
    if (x == y) return;
    if (rnk[x] < rnk[y]) swap(x, y);
    p[y] = x;
    if (rnk[x] == rnk[y]) rnk[x]++;
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> packets;
  vector<tuple<int, int, int>> qq;
  for (int i = 0; i < m; i++) {
    int t;
    cin >> t;
    if (t == 1) {
      int x, y;
      cin >> x >> y;
      x--, y--;
      adjList[y].push_back(x);
      qq.emplace_back(t, x, y);
    } else  if (t == 2) {
      int x;
      cin >> x;
      x--;
      packets.push_back(x);
    } else {
      int x, i;
      cin >> x >> i;
      x--, i--;
      qq.emplace_back(t, x, i);
    }
  }
  timer = 1;
  vector<int> tops;
  for (int i = 0; i < n; i++) {
    if (!tin[i])
      TopologicalSort(i, tops);
  }
  reverse(tops.begin(), tops.end());
  fill(tin.begin(), tin.end(), 0);
  for (int i = 0; i < n; i++) {
    if (!tin[tops[i]]) {
      dfs(tops[i]);
    }
  }
  Dsu dsu(n);
  for (auto cur : qq) {
    int t, x, y;
    tie(t, x, y) = cur;
    if (t == 1) {
      dsu.unite(x, y);
    } else {
      int p = x, c = packets[y];
      int a = dsu.getPar(p), b = dsu.getPar(c);
      if (a != b) cout << "NO";
      else if (tin[p] <= tin[c] && tout[p] >= tout[c]) cout << "YES";
      else cout << "NO";
      cout << '\n';
    }
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX = 1e5 + 10;

vector<vector<int>> adjList(MAX);
vector<int> tin(MAX, 0), tout(MAX, 0);

int timer = 0;

void TopologicalSort (int nd, vector<int>& tops) {
  tin[nd] = 1;
  for (int nxt : adjList[nd]) {
    if (!tin[nd])
      TopologicalSort(nxt, tops);
  }
  tops.push_back(nd);
}

void dfs (int nd) {
  tin[nd] = timer++;
  for (int nxt : adjList[nd]) {
    dfs(nxt);
  }
  tout[nd] = timer++;
}

class Dsu {
public:
  int n;
  vector<int> p, rnk;

  Dsu (int _n) : n(_n) {
    p = rnk = vector<int> (n, 0);
    iota(p.begin(), p.end(), 0);
  }

  int getPar (int x) {
    return p[x] == x ? x : p[x] = getPar(p[x]);
  }

  void unite (int a, int b) {
    int x = getPar(a), y = getPar(b);
    if (x != y) {
      if (rnk[x] < rnk[y]) swap(x, y);
      p[y] = x;
      if (rnk[x] == rnk[y]) rnk[x]++;
    }
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> packets;
  vector<pair<int, int>> qq;
  vector<tuple<int, int, int>> upd;
  for (int i = 0; i < m; i++) {
    int t;
    cin >> t;
    if (t == 1) {
      int x, y;
      cin >> x >> y;
      x--, y--;
      adjList[y].push_back(x);
      upd.emplace_back(t, x, y);
    } else  if (t == 2) {
      int x;
      cin >> x;
      x--;
      packets.push_back(x);
      upd.emplace_back(t, x, 0);
    } else {
      int x, i;
      cin >> x >> i;
      x--, i--;
      qq.emplace_back(i, x);
    }
  }
  timer = 1;
  vector<int> tops;
  for (int i = 0; i < n; i++) {
    if (!tin[i])
      TopologicalSort(i, tops);
  }
  reverse(tops.begin(), tops.end());
  fill(tin.begin(), tin.end(), 0);
  for (int i = 0; i < n; i++) {
    if (!tin[tops[i]]) {
      dfs(tops[i]);
    }
  }
  Dsu dsu(n);
  sort(qq.begin(), qq.end());
  int dn = 0, i = 0;
  for (auto cur : qq) {
    int x, y;
    tie(y, x) = cur;
    for (; i < (int) upd.size() && dn <= y; i++) {
      int t, u, v;
      tie(t, u, v) = upd[i];
      if (t == 1) {
        dsu.unite(u, v);
      } else dn++;
    }
    int p = x, c = packets[y];
    int a = dsu.getPar(p), b = dsu.getPar(c);
    if (a != b) cout << "NO";
    else if (tin[p] <= tin[c] && tout[p] >= tout[c]) cout << "YES";
    else cout << "NO";
    cout << '\n';
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX = 1e5 + 10;

vector<vector<int>> adjList(MAX);
vector<int> tin(MAX, 0), tout(MAX, 0);

int timer = 0;

void dfs (int nd) {
  tin[nd] = timer++;
  for (int nxt : adjList[nd]) {
    dfs(nxt);
  }
  tout[nd] = timer++;
}

class Dsu {
public:
  int n;
  vector<int> p, rnk;

  Dsu (int _n) : n(_n) {
    p = rnk = vector<int> (n, 0);
    iota(p.begin(), p.end(), 0);
  }

  int getPar (int x) {
    return p[x] == x ? x : p[x] = getPar(p[x]);
  }

  void unite (int a, int b) {
    int x = getPar(a), y = getPar(b);
    if (x != y) {
      if (rnk[x] < rnk[y]) swap(x, y);
      p[y] = x;
      if (rnk[x] == rnk[y]) rnk[x]++;
    }
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> packets, par(n);
  vector<vector<pair<int, int>>> qq(m);
  vector<tuple<int, int, int>> upd;
  iota(par.begin(), par.end(), 0);
  int qsz = 0;
  for (int i = 0, psz = 0; i < m; i++) {
    int t;
    cin >> t;
    if (t == 1) {
      int x, y;
      cin >> x >> y;
      x--, y--;
      adjList[y].push_back(x);
      par[x] = y;
      upd.emplace_back(t, x, y);
    } else  if (t == 2) {
      int x;
      cin >> x;
      x--;
      packets.push_back(x);
      upd.emplace_back(t, x, psz++);
    } else {
      int x, i;
      cin >> x >> i;
      x--, i--;
      qq[i].push_back({x, qsz++});
    }
  }
  timer = 1;
  for (int i = 0; i < n; i++) {
    if (par[i] == i) {
      dfs(i);
    }
  }
  Dsu dsu(n);
  vector<int> ans(qsz);
  for (auto cur : upd) {
    int t, x, y;
    tie(t, x, y) = cur;
    if (t == 1) {
      dsu.unite(x, y);
    } else {
      for (int i = 0; i < (int) qq[y].size(); i++) {
        int xx = qq[y][i].first;
        int pos = qq[y][i].second;
        int a = dsu.getPar(xx), b = dsu.getPar(x);
        if (a != b) ans[pos] = 0;
        else if (tin[xx] <= tin[x] && tout[xx] >= tout[x]) ans[pos] = 1;
        else ans[pos] = 0;
      }
    }
  }
  for (int ok : ans) {
    if (ok) cout << "YES\n";
    else cout << "NO\n";
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX = 1e5 + 10;

vector<vector<int>> adjList(MAX);
vector<int> tin(MAX, 0), tout(MAX, 0);

int timer = 0;

void TopologicalSort (int nd, vector<int>& tops) {
  tin[nd] = 1;
  for (int nxt : adjList[nd]) {
    TopologicalSort(nxt, tops);
  }
  tops.push_back(nd);
}

void dfs (int nd) {
  tin[nd] = timer++;
  for (int nxt : adjList[nd]) {
    dfs(nxt);
  }
  tout[nd] = timer++;
}

class Dsu {
public:
  int n;
  vector<int> p, rnk;

  Dsu (int _n) : n(_n) {
    p = rnk = vector<int> (n, 0);
    iota(p.begin(), p.end(), 0);
  }

  int getPar (int x) {
    return p[x] == x ? x : (p[x] = getPar(p[x]));
  }

  void unite (int a, int b) {
    int x = getPar(a), y = getPar(b);
    if (x == y) return;
    if (rnk[x] < rnk[y]) swap(x, y);
    p[y] = x;
    if (rnk[x] == rnk[y]) rnk[x]++;
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> packets;
  vector<tuple<int, int, int>> qq;
  for (int i = 0; i < m; i++) {
    int t;
    cin >> t;
    if (t == 1) {
      int x, y;
      cin >> x >> y;
      x--, y--;
      adjList[y].push_back(x);
      qq.emplace_back(t, x, y);
    } else  if (t == 2) {
      int x;
      cin >> x;
      x--;
      packets.push_back(x);
    } else {
      int x, i;
      cin >> x >> i;
      x--, i--;
      qq.emplace_back(t, x, i);
    }
  }
  timer = 1;
  vector<int> tops;
  for (int i = 0; i < n; i++) {
    if (!tin[i])
      TopologicalSort(i, tops);
  }
  reverse(tops.begin(), tops.end());
  fill(tin.begin(), tin.end(), 0);
  for (int i = 0; i < n; i++) {
    if (!tin[tops[i]]) {
      dfs(tops[i]);
    }
  }
  Dsu dsu(n);
  for (auto cur : qq) {
    int t, x, y;
    tie(t, x, y) = cur;
    if (t == 1) {
      dsu.unite(x, y);
    } else {
      int p = x, c = packets[y];
      int a = dsu.getPar(p), b = dsu.getPar(c);
      if (a != b) cout << "NO";
      else if (tin[p] < tin[c] && tout[p] > tout[c]) cout << "YES";
      else cout << "NO";
      cout << '\n';
    }
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX = 1e5 + 10;

vector<vector<int>> adjList(MAX);
vector<int> tin(MAX, 0), tout(MAX, 0);

int timer = 0;

void TopologicalSort (int nd, vector<int>& tops) {
  tin[nd] = 1;
  for (int nxt : adjList[nd]) {
    TopologicalSort(nxt, tops);
  }
  tops.push_back(nd);
}

void dfs (int nd) {
  tin[nd] = timer++;
  for (int nxt : adjList[nd]) {
    dfs(nxt);
  }
  tout[nd] = timer++;
}

class Dsu {
public:
  int n;
  vector<int> p, rnk;

  Dsu (int _n) : n(_n) {
    p = rnk = vector<int> (n, 0);
    iota(p.begin(), p.end(), 0);
  }

  int getPar (int x) {
    return p[x] == x ? x : (p[x] = getPar(p[x]));
  }

  void unite (int a, int b) {
    int x = getPar(a), y = getPar(b);
    if (x == y) return;
    if (rnk[x] < rnk[y]) swap(x, y);
    p[y] = x;
    if (rnk[x] == rnk[y]) rnk[x]++;
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> packets;
  vector<tuple<int, int, int>> qq;
  for (int i = 0; i < m; i++) {
    int t;
    cin >> t;
    if (t == 1) {
      int x, y;
      cin >> x >> y;
      x--, y--;
      adjList[y].push_back(x);
      qq.emplace_back(t, x, y);
    } else  if (t == 2) {
      int x;
      cin >> x;
      x--;
      packets.push_back(x);
    } else {
      int x, i;
      cin >> x >> i;
      x--, i--;
      qq.emplace_back(t, x, i);
    }
  }
  timer = 1;
  vector<int> tops;
  for (int i = 0; i < n; i++) {
    if (!tin[i])
      TopologicalSort(i, tops);
  }
  reverse(tops.begin(), tops.end());
  fill(tin.begin(), tin.end(), 0);
  for (int i = 0; i < n; i++) {
    if (!tin[tops[i]]) {
      dfs(tops[i]);
    }
  }
  Dsu dsu(n);
  for (auto cur : qq) {
    int t, x, y;
    tie(t, x, y) = cur;
    if (t == 1) {
      dsu.unite(x, y);
    } else {
      int p = x, c = packets[y];
      int a = dsu.getPar(p), b = dsu.getPar(c);
      if (a != b) cout << "NO";
      else if (tin[p] <= tin[c] && tout[p] >= tout[c]) cout << "YES";
      else cout << "NO";
      cout << '\n';
    }
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX = 1e5 + 10;

vector<vector<int>> adjList(MAX);
vector<int> tin(MAX, 0), tout(MAX, 0);

int timer = 0;

void TopologicalSort (int nd, vector<int>& tops) {
  tin[nd] = 1;
  for (int nxt : adjList[nd]) {
    if (!tin[nd])
      TopologicalSort(nxt, tops);
  }
  tops.push_back(nd);
}

void dfs (int nd) {
  tin[nd] = timer++;
  for (int nxt : adjList[nd]) {
    dfs(nxt);
  }
  tout[nd] = timer++;
}

class Dsu {
public:
  int n;
  vector<int> p, rnk;

  Dsu (int _n) : n(_n) {
    p = rnk = vector<int> (n, 0);
    iota(p.begin(), p.end(), 0);
  }

  int getPar (int x) {
    return p[x] == x ? x : p[x] = getPar(p[x]);
  }

  void unite (int a, int b) {
    int x = getPar(a), y = getPar(b);
    if (x != y) {
      if (rnk[x] < rnk[y]) swap(x, y);
      p[y] = x;
      if (rnk[x] == rnk[y]) rnk[x]++;
    }
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> packets;
  vector<pair<pair<int, int>, int>> qq;
  vector<tuple<int, int, int>> upd;
  for (int i = 0; i < m; i++) {
    int t;
    cin >> t;
    if (t == 1) {
      int x, y;
      cin >> x >> y;
      x--, y--;
      adjList[y].push_back(x);
      upd.emplace_back(t, x, y);
    } else  if (t == 2) {
      int x;
      cin >> x;
      x--;
      packets.push_back(x);
      upd.emplace_back(t, x, 0);
    } else {
      int x, i;
      cin >> x >> i;
      x--, i--;
      qq.push_back({{i, x}, (int) qq.size()});
    }
  }
  timer = 1;
  vector<int> tops;
  for (int i = 0; i < n; i++) {
    if (!tin[i])
      TopologicalSort(i, tops);
  }
  reverse(tops.begin(), tops.end());
  fill(tin.begin(), tin.end(), 0);
  for (int i = 0; i < n; i++) {
    if (!tin[tops[i]]) {
      dfs(tops[i]);
    }
  }
  Dsu dsu(n);
  sort(qq.begin(), qq.end());
  int qsz = qq.size();
  vector<int> ans(qsz);
  int dn = 0, i = 0;
  for (auto cur : qq) {
    int x = cur.first.second, y = cur.first.first;
    for (; i < (int) upd.size() && dn <= y; i++) {
      int t, u, v;
      tie(t, u, v) = upd[i];
      if (t == 1) {
        dsu.unite(u, v);
      } else dn++;
    }
    int p = x, c = packets[y];
    int a = dsu.getPar(p), b = dsu.getPar(c);
    if (a != b) ans[cur.second] = 0;
    else if (tin[p] <= tin[c] && tout[p] >= tout[c]) ans[cur.second] = 1;
    else ans[cur.second] = 0;
  }
  for (int ok : ans) {
    if (ok) cout << "YES\n";
    else cout << "NO\n";
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX = 1e5 + 10;

vector<vector<int>> adjList(MAX);
vector<int> tin(MAX, 0), tout(MAX, 0);

int timer = 0;

void TopologicalSort (int nd, vector<int>& tops) {
  tin[nd] = 1;
  for (int nxt : adjList[nd]) {
    if (!tin[nd])
      TopologicalSort(nxt, tops);
  }
  tops.push_back(nd);
}

void dfs (int nd) {
  tin[nd] = timer++;
  for (int nxt : adjList[nd]) {
    dfs(nxt);
  }
  tout[nd] = timer++;
}

class Dsu {
public:
  int n;
  vector<int> p, rnk;

  Dsu (int _n) : n(_n) {
    p = rnk = vector<int> (n, 0);
    iota(p.begin(), p.end(), 0);
  }

  int getPar (int x) {
    return p[x] == x ? x : p[x] = getPar(p[x]);
  }

  void unite (int a, int b) {
    int x = getPar(a), y = getPar(b);
    if (x != y) {
      if (rnk[x] < rnk[y]) swap(x, y);
      p[y] = x;
      if (rnk[x] == rnk[y]) rnk[x]++;
    }
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> packets;
  vector<pair<pair<int, int>, int>> qq;
  vector<tuple<int, int, int>> upd;
  for (int i = 0; i < m; i++) {
    int t;
    cin >> t;
    if (t == 1) {
      int x, y;
      cin >> x >> y;
      x--, y--;
      adjList[y].push_back(x);
      upd.emplace_back(t, x, y);
    } else  if (t == 2) {
      int x;
      cin >> x;
      x--;
      packets.push_back(x);
      upd.emplace_back(t, x, 0);
    } else {
      int x, i;
      cin >> x >> i;
      x--, i--;
      qq.push_back({{i, x}, (int) qq.size()});
    }
  }
  timer = 1;
  vector<int> tops;
  for (int i = 0; i < n; i++) {
    if (!tin[i])
      TopologicalSort(i, tops);
  }
  reverse(tops.begin(), tops.end());
  fill(tin.begin(), tin.end(), 0);
  for (int i = 0; i < n; i++) {
    if (!tin[tops[i]]) {
      dfs(tops[i]);
    }
  }
  Dsu dsu(n);
  sort(qq.begin(), qq.end());
  int qsz = qq.size();
  vector<string> ans(qsz);
  int dn = 0, i = 0;
  for (auto cur : qq) {
    int x = cur.first.second, y = cur.first.first;
    for (; i < (int) upd.size() && dn <= y; i++) {
      int t, u, v;
      tie(t, u, v) = upd[i];
      if (t == 1) {
        dsu.unite(u, v);
      } else dn++;
    }
    int p = x, c = packets[y];
    int a = dsu.getPar(p), b = dsu.getPar(c);
    if (a != b) ans[cur.second] = "NO";
    else if (tin[p] <= tin[c] && tout[p] >= tout[c]) ans[cur.second] = "YES";
    else ans[cur.second] = "NO";
  }
  for (string prn : ans) {
    cout << prn << '\n';
  }
  return 0;
}


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

long long expo(int base,long long pwr)
{
    long long ans=1,i;
    for(i=0;i<pwr;i++)
        ans = ans*2;
    return ans;
}

int main()
{
    int t;
    cin>>t;

    while(t--)
    {
        long long n;
        cin>>n;

        long long bits = log2(n);
        //cout<<bits<<" ";
        long long ans = 2*(expo(2,bits)-1) - bits;
        //cout<<ans<<" "<<bits<<endl;
        ans += bits+1;
        //cout<<ans<<endl;
        //cout<<n<<" "<<pow(2,bits)<<endl;
        bits = n - expo(2,bits);
        for(int i=0;i<=log2(bits);i++)
        {

            ans = ans + (i+1)*ceil(double(bits-expo(2,i)+1)/expo(2,i+1));
            //cout<<ans<<" ";
        }
         cout<<ans<<endl;
    }
}


#include<bits/stdc++.h>
using namespace std;
#define ll unsigned long long
#define PI 3.14159265
template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll t;
    cin >> t;

    while(t--)  {
        ll n;
        cin  >> n;
        ll ans = 0;
        while(n > 0)    {
            ll val = log2(n);
            ans += pow(2, val+1) - 1;
            n -= pow(2, val);
        }
        cout << ans <<  "\n";

    }
    return 0;

}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PI 3.14159265
template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll t;
    cin >> t;

    while(t--)  {
        ll n;
        cin  >> n;
        ll ans = 0;
        for(int i = 0; i < 60; i++) {
            if(n  & (1LL << i)) {
                ans += (1LL << (i+1)) - 1;
            }
        }
        cout << ans << "\n";

    }
    return 0;

}


#include<bits/stdc++.h>
using namespace std;
#define ll unsigned long long
#define PI 3.14159265
template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll t;
    cin >> t;

    while(t--)  {
        ll n;
        cin  >> n;
        ll ans = 0;
        while(n > 0)    {
            ll val = log2(n);
            ans += (ll)(pow(2, val+1)+0.5) - 1;
            n -= pow(2, val);
        }
        cout << ans <<  "\n";

    }
    return 0;

}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PI 3.14159265
template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll t;
    cin >> t;

    while(t--)  {
        ll n;
        cin  >> n;
        ll ans = 0;
        while(n > 0)    {
            ll val = log2(n);
            ans += pow(2, val+1) - 1;
            n -= pow(2, val);
        }
        cout << ans <<  "\n";

    }
    return 0;

}


#include<bits/stdc++.h>
using namespace std;
#define ll unsigned long long
#define PI 3.14159265
template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll t;
    cin >> t;

    while(t--)  {
        ll n;
        cin  >> n;
        ll ans = 0;
        for(int i = 1;  i <= n; i = i*2)    {
            ans += n/i;
        }
        cout << ans <<  "\n";

    }
    return 0;

}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PI 3.14159265
template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll t;
    cin >> t;

    while(t--)  {
        ll n;
        cin  >> n;
        ll ans = 0;
        while(n > 0)    {
            ll val = log2(n);
            ans += (ll)(pow(2, val+1)+0.5) - 1;
            n -= pow(2, val);
        }
        cout << ans <<  "\n";

    }
    return 0;

}


#include<bits/stdc++.h>
using namespace std;
#define int long long
int main(){
    int t,n,ans;
    cin>>t;
	while(t--)
	{
		cin>>n;ans=0;
		for(int i=1; n; n>>=1,++i)if(n&1)ans+=(1ll<<i)-1;
		printf("%I64d\n",ans);
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
    int t;
    cin>>t;
	while(t--)
	{
		ll n;
        cin>>n;
        ll ans=0;
        while(n>0)
        {
            ans+=n;
            n/=2;
        }
        cout<<ans<<"\n";
	}
	return 0;
}


#include<stdio.h>
#define int long long
int main(){
    register int t,n,ans;
    cin>>t;
	for(t--)
	{
		cin>>n;ans=0;
		for(register int i=1;n;n>>=1,++i)if(n&1)ans+=(1ll<<i)-1;
		printf("%I64d\n",ans);
	}
	return 0;
}


#include<stdio.h>
#define int long long
int main(){
    int t,n,ans;
    cin>>t;
	for(t--)
	{
		cin>>n;ans=0;
		for(int i=1; n; n>>=1,++i)if(n&1)ans+=(1ll<<i)-1;
		printf("%I64d\n",ans);
	}
	return 0;
}


#include<bits/stdc++.h>
#define int long long
int main(){
    int t,n,ans;
    cin>>t;
	while(t--)
	{
		cin>>n;ans=0;
		for(int i=1; n; n>>=1,++i)if(n&1)ans+=(1ll<<i)-1;
		printf("%I64d\n",ans);
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
long long dp[61];

int main ()
{
    int t;

        dp[0]=0;
        dp[1]=1;
        for(int i = 2;i<61;i++){
            dp[i] = dp[i-1]+i+dp[i-1];
        }
    cin >> t;
    while (t--)
    {

       long long n;
       cin >> n;
       long long ans = 0;
       while(n!=0)
       {

        long long k = log2(n);
        long long f = pow(2,k);
        long long d = (n-f);
        ans+= (dp[k]+k+1);
        n=d;
       }
       cout << ans << endl;

    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
long long dp[61];

int main ()
{
    int t;

        dp[0]=0;
        dp[1]=1;
        for(int i = 2;i<61;i++){
            dp[i] = dp[i-1]+i+dp[i-1];
        }
    cin >> t;
    while (t--)
    {

       long long n;
       cin >> n;
       long long ans = 0;
       while(n!=0)
       {

        long long k = log2(n);
        long long f = 1<<k;
        long long d = (n-f);
        ans+= (dp[k]+k+1);
        n=d;
       }
       cout << ans << endl;

    }

    return 0;
}