#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])
{
// cout << "upd xdd " << v << " " << it.centr << " " << it.out_edge << " " << query_ind << " edge\n";
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;
if(it.a == it.b)
{
cout << "yes\n";
query_ind++;
continue;
}
rep(i,min(siz(centroids[it.a]),siz(centroids[it.b])))
{
if(centroids[it.a][i].out_edge > query_ind && centroids[it.a][i].centr != it.a) continue;
if(centroids[it.a][i].centr == centroids[it.b][i].centr)
{
// 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].centr == it.a && (centroids[it.b][i].path_type == 1 || centroids[it.b][i].path_type == 0) && centroids[it.b][i].edge <= query_ind)
{
ans = 1;
break;
}
if(centroids[it.b][i].centr == it.b && (centroids[it.a][i].path_type == 2 || centroids[it.a][i].path_type == 0) && centroids[it.a][i].out_edge <= query_ind)
{
ans = 1;
break;
}
if(centroids[it.b][i].edge > query_ind || centroids[it.a][i].out_edge > query_ind) continue;
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])
{
// cout << it2.centr << " " << ans << " centr\n";
if(it2.edge > query_ind && it2.centr != it.a) continue;
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... |