from array import array class UnionFind: def __init__(self,size:int)->None: self.siz=size self.tree=array("i",[-1]*size) def leader(self,pos:int)->int: ret=pos while self.tree[ret]>=0: ret=self.tree[ret] if pos!=ret: self.tree[pos]=ret return ret def same(self,u:int,v:int)->bool: return self.leader(u)==self.leader(v) def merge(self,u:int,v:int)->bool: u=self.leader(u) v=self.leader(v) if u==v: return False if self.tree[u]int: return -self.tree[self.leader(pos)] def groups(self)->list[list[int]]: mem=[[] for i in range(self.siz)] for i in range(self.siz): mem[self.leader(i)].append(i) ret=[] for i in mem: if len(i)!=0: ret.append(i) return ret class DisjointSparseTable: def __init__(self,default:list,op,e=None): self.size=len(default) self.op=op self.e=e self.table=default*max(1,(self.size-1).bit_length()) index=self.size for i in range(1,(self.size-1).bit_length()): for j in range(self.size): if ((j>>i)<>i)&1: self.table[j+index]=op(self.table[j-1+index],self.table[j+index]) else: pos=((j>>i)<None: self.op=op self.e=e self.left=deque() self.leftop=deque([e()]) self.right=deque() self.rightop=deque([e()]) def append(self,v:any)->None: self.right.append(v) self.rightop.append(self.op(self.rightop[-1],v)) def appendleft(self,v:any)->None: self.left.append(v) self.leftop.append(self.op(v,self.leftop[-1])) def pop(self)->any: if len(self.right)==0: nl=[] while len(self.left)>0: nl.append(self.popleft()) self.leftop=deque([self.e()]) half=len(nl)//2 for i in nl[half:]: self.append(i) for i in nl[:half][::-1]: self.appendleft(i) self.rightop.pop() return self.right.pop() def popleft(self)->any: if len(self.left)==0: nr=[] while len(self.right)>0: nr.append(self.pop()) self.rightop=deque([self.e()]) half=len(nr)//2 for i in nr[half:]: self.appendleft(i) for i in nr[:half][::-1]: self.append(i) self.leftop.pop() return self.left.pop() def get_all(self): return self.op(self.leftop[-1],self.rightop[-1]) def __len__(self)->int: return len(self.left)+len(self.right) def __str__(self)->str: return str(list(self.left)[::-1])+str(list(self.right)) class FoldableQueue(FoldableDeque): def pop(self): assert False def popleft(self)->any: if len(self.left)==0: for i in reversed(self.right): self.appendleft(i) self.right=deque() self.rightop=deque([self.e()]) self.leftop.pop() return self.left.pop() from collections import deque def order_min(x,y): if srt[x]v: u,v=v,u return dst[u:v+1] INF=(1<<61)-1 N,L,R=map(int,input().split()) A=list(map(int,input().split())) uni=UnionFind(N) for i in range(N): A[i]-=1 uni.merge(i,A[i]) cycle=[0]*N giant=A[:] for i in range(30): giant=[giant[giant[i]] for i in range(N)] cycle_number=[-1]*N cycles_size=[0]*(N+1) for i in range(N): if cycle_number[giant[i]]!=-1: continue size=1 cycle_number[giant[i]]=0 pos=A[giant[i]] while cycle_number[pos]==-1: cycle_number[pos]=size pos=A[pos] size+=1 cycle[uni.leader(i)]=size cycles_size[size]=uni.size(i) for i in range(N): cycle[i]=cycle[uni.leader(i)] tree=[[] for i in range(N+1)] for i in range(N): if cycle_number[i]==-1: tree[A[i]].append(i) else: tree[N].append(i) root=[0]*(N+1) for i in tree[N]: root[i]=i deep=[0]*(N+1) tour=[] srt=[-1]*(N+1) vert=deque([N]) while vert: pos=vert.pop() if pos<0: tour.append(-pos-1) continue srt[pos]=len(tour) tour.append(pos) for i in tree[pos]: deep[i]=deep[pos]+1 root[i]=max(root[i],root[pos]) vert.append(-pos-1) vert.append(i) dps=[[] for i in range(N+1)] for i in range(N+1): if cycles_size[i]==0: continue dp=[INF]*cycles_size[i] seg=[INF]*(i*4) for j in range(i+1): lf=L*j ri=R*j+1 if ri-lf>=i: seg[1]=min(seg[1],j) break lf%=i ri%=i if lf>=ri: ri+=i lf+=i*2 ri+=i*2 while lf>=1 ri>>=1 for j in range(i*2): pos=j+i*2 while pos>0: dp[j%i]=min(dp[j%i],seg[pos]) pos>>=1 que=FoldableQueue(min,lambda:INF) for j in range(R,L-1,-1): que.append(dp[(-j)%i]) for j in range(i,cycles_size[i]): dp[j]=que.get_all()+1 que.popleft() que.append(dp[max(j+1-L,(j+1-L)%i)]) for j in range(cycles_size[i]): if dp[j]>=INF: dp[j]=-1 dps[i]=dp dst=DisjointSparseTable(tour,order_min) Q=int(input()) for i in range(Q): S,T=map(int,input().split()) S-=1 T-=1 if not uni.same(S,T): print(-1) continue cyc=cycle[root[S]] dist=deep[S]-deep[T]+(cycle_number[root[T]]-cycle_number[root[S]])%cyc if cycle_number[T]==-1: if lca(S,T)!=T: print(-1) continue ans=(dist+R-1)//R if L*ans<=dist<=R*ans: print(ans) else: print(-1) continue print(dps[cyc][dist])