#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ll long long
#define ld long double
#define ull unsigned long long
#define ff first
#define ss second
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define rep(i, b) for(int i = 0; i < (b); ++i)
#define rep2(i,a,b) for(int i = a; i <= (b); ++i)
#define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c)
#define count_bits(x) __builtin_popcountll((x))
#define all(x) (x).begin(),(x).end()
#define siz(x) (int)(x).size()
#define forall(it,x) for(auto& it:(x))
using namespace __gnu_pbds;
using namespace std;
typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set;
//mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());}
//ll los(ll a, ll b) {return a + (mt() % (b-a+1));}
const int INF = 1e9+50;
const ll INF_L = 1e18+40;
const ll MOD = 1e9+7;
struct node
{
    int l = 0;
    int r = (1 << 17)-1;
    node* left;
    node* right;
    bool is_l = 0;
    bool is_r = 0;
    int sum = 0;
    void getl()
    {
        if(is_l) return;
        left = new node;
        left -> l = l;
        left -> r = (l+r)/2;
        is_l = 1;
    }
    void getr()
    {
        if(is_r) return;
        right = new node;
        right -> l = (l+r)/2+1;
        right -> r = r;
        is_r = 1;
    }
    int get_sum(int p1, int p2)
    {
        if(r < p1 || l > p2) return 0;
        if(l >= p1 && r <= p2) return sum;
        getl(); getr();
        return left->get_sum(p1,p2) + right->get_sum(p1,p2);
    }
    void add(int ind, int x)
    {
        if(l == r)
        {
            sum += x;
            return;
        }
        getl();getr();
        if(ind <= (l+r)/2) left->add(ind,x);
        else right->add(ind,x);
        sum = left->sum + right->sum;
    }
};
struct query
{
    int type,a,b;
};
struct centr_str
{
    int centr, path_type, edge, out_edge;
};
vector<query> queries;
vector<pii> graph[120'001];
vector<centr_str> centroids[120'001];
bitset<120'001> odw;
int subtree[120'001];
node seg_tree[120'001];
void calc_subtree(int v, int pop)
{
    subtree[v] = 1;
    forall(it,graph[v])
    {
        if(it.ff != pop && !odw[it.ff])
        {
            calc_subtree(it.ff,v);
            subtree[v] += subtree[it.ff];
        }
    }
}
void calc_paths(int v, int pop, int path_type, int pop_edge, int centr, int start_edge)
{
    centroids[v].pb({centr,path_type,start_edge,pop_edge});
    if(v == centr)
    {
        forall(it,graph[v])
        {
            if(it.ff != pop && !odw[it.ff])
            {
                calc_paths(it.ff,v,0,it.ss,centr,it.ss);
            }
        }
    }
    else
    {
        forall(it,graph[v])
        {
            if(it.ff != pop && !odw[it.ff])
            {
                if(path_type == 0)
                {
                    if(it.ss < pop_edge)
                    {
                        calc_paths(it.ff,v,1,it.ss,centr,start_edge);
                    }
                    else
                    {
                        calc_paths(it.ff,v,2,it.ss,centr,start_edge);
                    }
                }
                if(path_type == 1)
                {
                    if(it.ss < pop_edge)
                    {
                        calc_paths(it.ff,v,1,it.ss,centr,start_edge);
                    }
                    else
                    {
                        calc_paths(it.ff,v,-1,it.ss,centr,start_edge);
                    }
                }
                if(path_type == 2)
                {
                    if(it.ss > pop_edge)
                    {
                        calc_paths(it.ff,v,2,it.ss,centr,start_edge);
                    }
                    else
                    {
                        calc_paths(it.ff,v,-1,it.ss,centr,start_edge);
                    }
                }
                if(path_type == -1)
                {
                    calc_paths(it.ff,v,-1,it.ss,centr,start_edge);
                }
            }
        }
    }
}
void centroid(int v, int n)
{
   // cout << v << " start\n"; 
    calc_subtree(v,v);
    int pop = -1;
    while(true)
    {
        pii maks = {-1,-1};
        forall(it,graph[v])
        {
            if(it.ff != pop && !odw[it.ff])
            {
             //   cout << it.ff << " " << odw[it.ff] << " " << subtree[it.ff] << " subntree\n";
                maks = max(maks,{subtree[it.ff],it.ff});
            }
        }
        if(maks.ff > n/2)
        {
            pop = v;
            v = maks.ss;
        }
        else break;
    }
   // cout << v << " centr\n";
    calc_subtree(v,v);
    odw[v] = 1;
    calc_paths(v,v,0,-1,v,(1 << 17)-2);
    if(n == 1) return;
    forall(it,graph[v])
    {
        if(!odw[it.ff])
        {
            centroid(it.ff,subtree[it.ff]);
        }
    }
}
void upd_v(int v, int query_ind)
{
    forall(it,centroids[v])
    {
        if(it.out_edge != query_ind || it.centr == v) continue;
   //     cout << "upd " << v << " " << it.centr << " " << it.edge << " edge\n";
        if(it.path_type == 2 || it.path_type == 0)
        {
            seg_tree[it.centr].add(it.edge,1);
        }
    }
  //  cout << "\n";
}
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //random_start();
    int n,k;
    cin >> n >> k;
    rep(i,n+k-1)
    {
        char t;
        cin >> t;
        if(t == 'S')
        {  
            int a,b;
            cin >> a >> b;
            graph[a].pb({b,i});
            graph[b].pb({a,i});
            queries.pb({0,a,b});
        }
        if(t == 'Q')
        {
            int a,b;
            cin >> a >> b;
            queries.pb({1,a,b});
        }
        if(t == 'C')
        {
            int x;
            cin >> x;
            queries.pb({2,x,-1});
        }
    }
    centroid(1,n);
    int query_ind = 0;
    rep2(i,1,n)
    {
        seg_tree[i].add((1 << 17)-2,1);
    }
    forall(it,queries)
    {
        if(it.type == 0)
        {
            upd_v(it.a,query_ind);
            upd_v(it.b,query_ind);
        }
        if(it.type == 1)
        {
            bool ans = 0;
            rep(i,min(siz(centroids[it.a]),siz(centroids[it.b])))
            {
              //  cout << centroids[it.a][i].centr << " " << centroids[it.a][i].path_type << " " << centroids[it.a][i].edge << " " << centroids[it.a][i].out_edge << " centr a\n";
               //     cout << centroids[it.b][i].centr << " " << centroids[it.b][i].path_type << " " << centroids[it.b][i].edge << " " << centroids[it.b][i].out_edge << " centr b\n\n";
                    
                if(centroids[it.a][i].out_edge > query_ind) continue;
                if(centroids[it.a][i].centr == centroids[it.b][i].centr)
                {
                    if(centroids[it.b][i].centr == it.b && (centroids[it.a][i].path_type == 2 || centroids[it.a][i].path_type == 0))
                    {
                        ans = 1;
                        break;
                    }
                    if(centroids[it.a][i].centr == it.a && (centroids[it.b][i].path_type == 1 || centroids[it.b][i].path_type == 1))
                    {
                        ans = 1;
                        break;
                    }
                    if((centroids[it.a][i].path_type == 0 || centroids[it.a][i].path_type == 2) && (centroids[it.b][i].path_type == 1 || centroids[it.b][i].path_type == 0) && centroids[it.b][i].edge < centroids[it.a][i].edge)
                    {
                        ans = 1;
                        break;
                    }
                }
            }
            if(ans == 1)
            {
                cout << "yes\n";
            }
            else
            {
                cout << "no\n";
            }
        }
        if(it.type == 2)
        {
            int ans = 0;
            forall(it2,centroids[it.a])
            {
                if(it2.path_type == 0 || it2.path_type == 1)
                {
                    if(it2.centr != it.a) ans += seg_tree[it2.centr].get_sum(it2.edge+1,(1 << 17)-2);
                    else ans += seg_tree[it2.centr].get_sum(0,(1 << 17)-2);
                }
            }
            cout << ans << "\n";
        }
        query_ind++;
    }
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |