传送门

为了方便,定义a[i]=g[i]a[i]=g[i]

首先做一次差分,将y=lrdist(y,x)\sum _{y=l} ^r dist(y,x)变成y=lxdist(y,x)y=r+1xdist(y,x)\sum _{y=l}^x dist(y,x) - \sum _{y=r+1}^x dist(y,x)

问题转换为给定l,rl,r,求i=lr1dist(i,r)\sum_{i=l}^{r-1} dist(i,r)

不要从最短路的方向考虑,而是考虑从xx点走kk步能够到达的点是哪些

首先,考虑k=1k=1,显然能够到达的点是[a[x],x1][a[x],x-1],并且,k=1k=1是最少的可能步数,于是x>[a[x],x1]x->[a[x],x-1]的最短路已经钦定为11了,注意到只有这些点到xx的步数是11,于是以后的任何点到xx的最短路绝对不是11

考虑k=2k=2,(敲黑板),我们巧妙地定义m[i],p[i]m[i],p[i]数组,表示[i,n][i,n]的点走一步能够走到的最左的点,显然m[i]=mina[j],(j[i,n]),p[i]m[i]= \min\\{ a[j] \\},(j\in [i,n]),p[i]代表这个jj,之后你就会发现它非常有用。

注意到m[i]m[i]有一个特殊的性质,$\forall x \in [m[i],p[i]-1] ,都能通过道路p[i]->x$到达(也是废话,但是最容易忽略)

我们接着证明[m[a[x],a[x]1][m[a[x],a[x]-1]的所有点都可以通过22条道路从xx到达:

1.若p[a[x]][a[x],x1]p[a[x]] \in [a[x],x-1]

那么可以通过两条道路x>p[a[x]](p[a[x]][a[x],x1])x->p[a[x]] (\because p[a[x]] \in [a[x],x-1])

p[a[x]]>y[m[a[x],a[x]1](p[a[x]]>=a[x])p[a[x]] -> \forall y \in [m[a[x],a[x]-1] (\because p[a[x]] >= a[x])

到达。

如果这里没有明白请回去看一下刚才说的性质。

2.若p[a[x]][x+1,n]p[a[x]] \in [x+1,n],注意到我们说的性质,$\forall y \in [m[a[x]],p[a[x]]-1] ,都可以通过一条道路p[a[x]->y到达,\because x<p[a[x]] \therefore$ 存在x>p[a[x]]x->p[a[x]]的道路。于是我们直接从x>p[a[x]]x->p[a[x]],再p[a[x]]>y[m[a[x],a[x]1]p[a[x]]-> \forall y \in [m[a[x],a[x]-1]即可通过两次到达。

3.若p[a[x]]=xp[a[x]] = x ,显然这样是不行的,因为a[x]>m[a[i]]a[x] > m[a[i]]

考虑k=3k=3,记m[a[x]]=x1m[a[x]]=x_1,所以有[m[x1],x11][m[x_1],x_1-1]的点可以通过33次到达。

考虑k=4k=4,记m[a[x1]]=x2m[a[x_1]]=x_2,所以有[m[x2],x21][m[x_2],x_2-1]的点可以通过44次到达。

……………………

最终这个最短路序列被分成$[a[x],x-1],[m[a[x]],a[x]-1],[m[m[a[x]]],m[a[x]]-1] , \cdots , [1, ...] $等部分,他们对答案的贡献分别是1,2,3,4,1,2,3,4,\cdots

不妨考虑换一种方法记录这个答案,这个答案等价于$x-1+(a[x]-1)+(m[a[x]]-1)+(m[m[a[x]]]-1)+(m[m[m[a[x]]]]-1) \cdots $

发现了什么,m[m[]]m[m[]]嵌套的格式让我们想起了倍增,于是我们记录to[i][j]to[i][j],代表m[m[m[...m[j]...]]m[m[m[...m[j]...]]的值,其中嵌套了2i2^im[]m[]

同样,也要记录sum[i][j]sum[i][j],代表上面那个东西的前缀和。

到了最终的问题,如何算出i=lr1dist(i,r)\sum_{i=l}^{r-1} dist(i,r),考虑到我们在上面的计算过程中重复算了很多值,我们现在要一个一个减去,记mink,使m[m[m[..(km)..m[x]]]]l\min\\{ k,使得m[m[m[..(k个m)..m[x]]]] \le l \\},只有嵌套k\le k次的m[m[]]m[m[ ]]才会对答案造成贡献,于是我们只要求出前kk个即可。

而且注意到我们重复算了很多东西,对于[1,l1][1,l-1]的数,每次都会被重复算,于是减去k(l1)k*(l-1)即可。

这样就完了。

注意代码里面有一个小特判,如果a[r]la[r]\le l,那么每个数都可以通过一次调到rr,答案就是rlr-l

#include <bits/stdc++.h>
#define MAXN 300005
#define LOG 25
using namespace std;
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while (ch<'0'||ch>'9'){
		if (ch=='-') f=-1;
		ch=getchar();
	}
	while (ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}
int a[MAXN],m[MAXN];
int to[MAXN][LOG],sum[MAXN][LOG];
inline int Calc(int l,int r){//sigma_{i=l}^r-1 dist(i,r)
	if (a[r]<=l) return (r-1)-l+1;
	int s=r-1,p=a[r],cnt=0;
	for (register int i=LOG-1;i>=0;--i){
		if (to[p][i]>l){//可以跳
			cnt|=(1<<i);
			s+=sum[p][i];
			p=to[p][i];
		}
	}
	s+=(p-1),cnt+=2;
	return s-cnt*(l-1);//去掉前面部分
}
int main(){
	int n=read();
	for (register int i=2;i<=n;++i) a[i]=read();
	m[n]=a[n];
	for (register int i=n-1;i>=1;--i){
		m[i]=min(m[i+1],a[i]);
	}
	for (register int i=1;i<=n;++i) to[i][0]=m[i],sum[i][0]=i-1;
	for (register int j=1;j<LOG;++j){
		for (register int i=1;i<=n;++i){
			to[i][j]=to[to[i][j-1]][j-1];
			sum[i][j]=sum[i][j-1]+sum[to[i][j-1]][j-1];
		}
	}
	int q=read();
	while (q--){
		int l=read(),r=read(),x=read();
		int ans=Calc(l,x)-Calc(r+1,x);
		int down=r-l+1;
		int g=__gcd(ans,down);
		printf("%d/%d\n",ans/g,down/g);
	}
}