#define PROBLEM "https://judge.yosupo.jp/problem/jump_on_tree"
#include<bits/stdc++.h>#include"library/tree/Tree.hpp"
#include"library/tree/HLD.hpp"intmain(){std::ios::sync_with_stdio(false);std::cin.tie(nullptr);intn,q;std::cin>>n>>q;TreeT(n);T.scan(0);HLDhld(T);hld.build();while(q--){intu,v,k;std::cin>>u>>v>>k;std::cout<<hld.jump(u,v,k)<<"\n";}}
#line 1 "test/library-checker/Tree/JumpOnTree.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/jump_on_tree"
#include<bits/stdc++.h>#line 2 "library/graph/Graph.hpp"
#line 6 "library/graph/Graph.hpp"
structEdge{intfrom,to;Edge()=default;Edge(intfrom,intto):from(from),to(to){}operatorint()const{returnto;}};structGraph{intn;usingedge_type=Edge;std::vector<edge_type>edges;protected:std::vector<int>in_deg;boolprepared;classOutgoingEdges{Graph*g;intl,r;public:OutgoingEdges(Graph*g,intl,intr):g(g),l(l),r(r){}edge_type*begin(){return&(g->edges[l]);}edge_type*end(){return&(g->edges[r]);}edge_type&operator[](inti){returng->edges[l+i];}intsize()const{returnr-l;}};classConstOutgoingEdges{constGraph*g;intl,r;public:ConstOutgoingEdges(constGraph*g,intl,intr):g(g),l(l),r(r){}constedge_type*begin()const{return&(g->edges[l]);}constedge_type*end()const{return&(g->edges[r]);}constedge_type&operator[](inti)const{returng->edges[l+i];}intsize()const{returnr-l;}};public:OutgoingEdgesoperator[](intv){assert(prepared);return{this,in_deg[v],in_deg[v+1]};}constConstOutgoingEdgesoperator[](intv)const{assert(prepared);return{this,in_deg[v],in_deg[v+1]};}boolis_prepared()const{returnprepared;}Graph():n(0),in_deg(1,0),prepared(false){}Graph(intn):n(n),in_deg(n+1,0),prepared(false){}Graph(intn,intm,booldirected=false,intindexed=1):n(n),in_deg(n+1,0),prepared(false){scan(m,directed,indexed);}voidresize(intn){n=n;}voidadd_arc(intfrom,intto){assert(!prepared);assert(0<=fromandfrom<nand0<=toandto<n);edges.emplace_back(from,to);in_deg[from+1]++;}voidadd_edge(intu,intv){add_arc(u,v);add_arc(v,u);}voidadd_arc(constedge_type&e){add_arc(e.from,e.to);}voidadd_edge(constedge_type&e){add_edge(e.from,e.to);}voidscan(intm,booldirected=false,intindexed=1){edges.reserve(directed?m:2*m);while(m--){intu,v;std::cin>>u>>v;u-=indexed;v-=indexed;if(directed)add_arc(u,v);elseadd_edge(u,v);}build();}voidbuild(){assert(!prepared);prepared=true;for(intv=0;v<n;v++)in_deg[v+1]+=in_deg[v];std::vector<edge_type>new_edges(in_deg.back());autocounter=in_deg;for(auto&&e:edges)new_edges[counter[e.from]++]=e;edges=new_edges;}voidgraph_debug()const{#ifndef __LOCAL
return;#endif
assert(prepared);for(intfrom=0;from<n;from++){std::cerr<<from<<";";for(inti=in_deg[from];i<in_deg[from+1];i++)std::cerr<<edges[i].to<<" ";std::cerr<<"\n";}}};#line 3 "library/tree/Tree.hpp"
structTree:Graph{usingGraph::Graph;Tree()=default;introot=-1;std::vector<int>DFS,BFS,depth;voidscan_root(intindexed=1){for(inti=1;i<n;i++){intp;std::cin>>p;add_edge(p-indexed,i);}build();}voidscan(intindexed=1){Graph::scan(n-1,false,indexed);build();}edge_type&parent(intv){assert(~rootandroot!=v);return(*this)[v][0];}constedge_type&parent(intv)const{assert(~rootandroot!=v);return(*this)[v][0];}OutgoingEdgesson(intv){assert(~root);if(v==root)return{this,in_deg[v],in_deg[v+1]};return{this,in_deg[v]+1,in_deg[v+1]};}private:voiddfs(intv,intpre=-1){for(auto&e:(*this)[v]){if(e.to==pre)std::swap((*this)[v][0],e);else{depth[e.to]=depth[v]+1;dfs(e.to,v);}}DFS.push_back(v);}public:voidbuild(intr=0){if(!is_prepared())Graph::build();if(~root){assert(r==root);return;}root=r;depth=std::vector<int>(n,0);DFS.reserve(n);BFS.reserve(n);dfs(root);std::queue<int>que;que.push(root);while(que.size()){intp=que.front();que.pop();BFS.push_back(p);for(constauto&e:son(p))que.push(e.to);}}};#line 2 "library/tree/HLD.hpp"
template<typenameTREE>structHLD{intn;TREET;std::vector<int>sz,head,id,id2,rev_id;boolprepared;HLD(TREET_):T(T_),n(T_.n),sz(n),head(n),id(n),id2(n),rev_id(n),prepared(false){}HLD()=default;private:voiddfs_sz(intv){sz[v]=1;for(auto&e:T.son(v)){dfs_sz(e.to);sz[v]+=sz[e.to];if(sz[e.to]>sz[T.son(v)[0].to])std::swap(e,T.son(v)[0]);}}voiddfs_hld(intv,int&k){id[v]=k++;rev_id[id[v]]=v;for(inti=0;i<T.son(v).size();i++){intto=T.son(v)[i];head[to]=(i?to:head[v]);dfs_hld(to,k);}id2[v]=k;}public:std::vector<int>build(intr=0){assert(!prepared);prepared=true;if(~T.root)assert(T.root==r);elseT.build(r);head[r]=r;dfs_sz(r);intk=0;dfs_hld(r,k);returnid;}intlca(intu,intv)const{assert(prepared);while(head[u]!=head[v])if(T.depth[head[u]]>T.depth[head[v]])u=T.parent(head[u]);elsev=T.parent(head[v]);return(T.depth[u]<T.depth[v]?u:v);}intdistance(intu,intv)const{intw=lca(u,v);returnT.depth[u]+T.depth[v]-T.depth[w]*2;}// v の k 個上の頂点を返すintkth_parent(intv,intk)const{assert(prepared);if(T.depth[v]<k)return-1;while(T.depth[v]-T.depth[head[v]]<k){k-=T.depth[v]-T.depth[head[v]]+1;v=T.parent(head[v]);}returnrev_id[id[v]-k];}// u から v へ k 回移動した頂点を返すintjump(intu,intv,intk)const{assert(prepared);intw=lca(u,v);if(T.depth[u]+T.depth[v]-T.depth[w]*2<k)return-1;if(T.depth[u]-T.depth[w]>=k)returnkth_parent(u,k);returnkth_parent(v,T.depth[u]+T.depth[v]-T.depth[w]*2-k);}// l=lca(u,v) とした時、[u,l] パスと [v,l] パス を閉区間の組みで返すusingpath_t=std::vector<std::pair<int,int>>;std::pair<path_t,path_t>path(intu,intv)const{assert(prepared);path_tpath_u,path_v;while(u!=v){if(head[u]==head[v]){if(T.depth[u]<T.depth[v])path_v.emplace_back(id[v],id[u]);elsepath_u.emplace_back(id[u],id[v]);break;}if(T.depth[head[u]]<T.depth[head[v]]){path_v.emplace_back(id[v],id[head[v]]);v=T.parent(head[v]);}else{path_u.emplace_back(id[u],id[head[u]]);u=T.parent(head[u]);}}if(u==v)path_u.emplace_back(id[u],id[u]);return{path_u,path_v};}// [l,r) が v の部分木std::pair<int,int>subtree(intv)const{assert(prepared);return{id[v],id2[v]};}};#line 6 "test/library-checker/Tree/JumpOnTree.test.cpp"
intmain(){std::ios::sync_with_stdio(false);std::cin.tie(nullptr);intn,q;std::cin>>n>>q;TreeT(n);T.scan(0);HLDhld(T);hld.build();while(q--){intu,v,k;std::cin>>u>>v>>k;std::cout<<hld.jump(u,v,k)<<"\n";}}