#include <bits/stdc++.h>
using namespace std;
#define int long long
#define vo vector
#define pb push_back
#define se second
#define fi first
#define all(v) v.begin(), v.end()
typedef vector<int> vi;
typedef pair<int, int> pii;
#define rep(i, a, b) for(int i=(a); i<b; i++)
#define pr1(x) cerr << #x << '=' << x << ' ';
//for google contests
#define umap unordered_map
#define uset unordered_set
#define repd(i, a, b) for(int i=(b-1); i >= a; i--)
void _pr(signed x) {cerr << x;}
void _pr(long long x) {cerr << x;}
void _pr(size_t x) {cerr << x;}
void _pr(string &x) {cerr << x;}
void _pr(double x) {cerr << x;}
void _pr(char x) {cerr << '\'' << x << '\'';}
void _pr(const char* x) {cerr << x;}
void _pr(bool x) {cerr << (x ? "true" : "false");}
template<typename T, typename V> void _pr(const pair<T, V> &x);
template<typename T, typename V> void _pr(const pair<T, V> &x) {cerr << "\e[95m" << "[ "; _pr(x.first); cerr << ", "; _pr(x.second); cerr << "\e[95m" << ']';}
template<typename T> void _pr(const T &x) {int F=0; cerr << '{'; for(auto &i: x) cerr << (F++ ? ", " : ""), _pr(i); cerr << "\e[91m" << '}';}
template <typename T, typename... V> void _pr(T t, V... v) {_pr(t); if(sizeof...(v)) cerr << ", "; _pr(v...);}
#define pr(x...) cerr << "\e[91m" << __func__ << ':' << __LINE__ << " [" << #x << "] = ["; _pr(x); cerr << "\e[91m" << ']' << "\033[0m" << endl;
mt19937 mt_rng(chrono::steady_clock::now().time_since_epoch().count());
int rand(int l, int r){return uniform_int_distribution<int>(l, r)(mt_rng);}
//go for outline with ;, then details
int const inf = 1e18, mxn = 1e5+2e4+5;
int const mxlog = 25;
int n, q, lastedge[mxn][mxlog], maxedge[mxn][mxlog];
vo<vo<pii>> adj(mxn);
vi upIncr, upDecr;
int bl[mxn][mxlog], dep[mxn];
void dfs(int at, int p, int depth, int prevind, int incr){
dep[at] = depth; bl[at][0] = p; lastedge[at][0] = prevind; maxedge[at][0] = prevind;
rep(i, 1, mxlog){
bl[at][i] = bl[bl[at][i-1]][i-1];
lastedge[at][i] = lastedge[bl[at][i-1]][i-1];
maxedge[at][i] = max(maxedge[at][i-1], maxedge[bl[at][i-1]][i-1]);
}
if(incr>=0) upDecr[at] = incr;
else upIncr[at] = -incr;
for(auto [x, ind]: adj[at]){
if(x==p) continue;
if(prevind<ind){
if(incr>=0) dfs(x, at, depth+1, ind, incr+1);
else dfs(x, at, depth+1, ind, 0);
}
else{
if(incr>=0) dfs(x, at, depth+1, ind, 0);
else dfs(x, at, depth+1, ind, incr-1);
}
}
}
int jmp(int v, int d){
rep(i, 0, mxlog){
if((d>>i) & 1) v = bl[v][i];
}
return v;
}
int LCA(int a, int b){
if(dep[a] < dep[b]) swap(a, b);
int d = dep[a]-dep[b];
a = jmp(a, d);
if(a==b) return a;
repd(i, 0, mxlog){
if(bl[a][i] != bl[b][i]){
a = bl[a][i], b = bl[b][i];
}
}
return bl[a][0];
}
pii LASTEDGE(int v, int d){ // lastedge, maxedge
int edgeind, mxedge=-1;
rep(i, 0, mxlog){
if((d>>i) & 1){
mxedge = max(mxedge, maxedge[v][i]);
edgeind = lastedge[v][i];
v = bl[v][i];
}
}
return {edgeind, mxedge};
}
bool is_storing(int a, int b, int MAXTIME){ // is path from b to a increasing
if(a==b) return 1;
int lca = LCA(a, b);
int upB = upIncr[b], upA = upDecr[a];
if(dep[b]-upB<=dep[lca] && dep[a]-upA<=dep[lca]){
pii edgeA = LASTEDGE(a, dep[a]-dep[lca]), edgeB = LASTEDGE(b, dep[b]-dep[lca]);
int maxtime = max(edgeA.se, edgeB.se);
if((a==lca || b==lca) && maxtime<=MAXTIME) return 1;
if(edgeA.fi < edgeB.fi && maxtime<=MAXTIME) return 1;
}
return 0;
}
signed main(){
cin.tie(0)->sync_with_stdio(0);
cin>>n>>q;
upDecr.assign(n, 0); upIncr.assign(n, 0);
int timer=0;
vo<array<int, 3>> queries;
rep(i, 0, n+q-1){
char t; int a, b; cin>>t;
if(t=='S'){
cin>>a>>b; a--, b--;
adj[a].pb({b, timer}); adj[b].pb({a, timer});
}
else if(t=='Q'){
cin>>a>>b; a--, b--; //does a store b,
queries.pb({a, b, timer});
}
else{
cin>>a; a--;
queries.pb({-1, a, timer});
}
timer++;
}
dfs(0, 0, 0, -1, 0);
// pr(upIncr)
// pr(upDecr)
for(auto [a, b, tme]: queries){
if(a==-1) cout << "1\n";
else cout << (is_storing(a, b, tme) ? "yes" : "no") << "\n";
}
}
/*
to find if path from node to ancestor is increasing, store farthest increase upwards from each node.
easily precomputed with dfs
storing in binary lifting is more brain power
*/
# | 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... |