1.倍增
#include <iostream>
const int N = 100000 + 5000;
const int M = 21;
int a[N];
int t[N];
int n;
int f[N][M];//从第i站转车2的j次方到的站
int g[N][M];//从第i站专车2的j次方到的站用的时间
void init()
{
for (int i = 1 ; i <= n ; i ++)
{
f[i][0] = a[i];
g[i][0] = t[i];
}//2的0次方
for (int i = 1 ; i <= 20; i ++)
{
for (int j = 1 ; j <= n ; j ++)
{
f[j][i] = f[f[j][i - 1]][i - 1];//先跳一半,再跳一半
g[j][i] = g[j][i - 1] + g[f[j][i - 1]][i - 1];//前一段的时间加上后一段
}
}
}
void solve()
{
int m;
std :: cin >> m;
int r = 1;//从1号站出发
int time = 0;//时间
for (int i = 20; i >= 0 ; i --)//移动2的i次方站
{
if ((1 << i) <= m)
{
time += g[r][i];//从r出发移动2的j次方站所用的时间
r = f[r][i];//从r出发移动2的i次方站
m -= (1 << i);//移动
if (m == 0) break;//完了
}
}
std :: cout << r << " " << time << "\n";
}
int main()
{
std :: cin >> n;
for (int i = 1 ; i <= n ; i ++)
{
std :: cin >> a[i] >> t[i];
}
int m;
std :: cin >> m;
init();//初始化
while (m --) solve();
}
### 区间最大值和最小值
```cpp
#include
const int N = 100005;
int h[N];
int n;
int f[N][21];//从i开始2的j次方个数最大值
int g[N][21];//从i开始2的j次方个数最小值
int lg[N];
void init()
{
for (int i = 1 ; i <= n ; i ++)
{
f[i][0] = h[i];
g[i][0] = h[i];
}
for (int i = 1 ; i <= 20 ; i ++)
{
for (int j = 1 ; j + (1 << i) -1 <= n; j ++)
{
f[j][i] = std :: max(f[j][i - 1],f[j + (1 << (i - 1))][i - 1]);
g[j][i] = std :: min(g[j][i - 1],g[j + (1 << (i - 1))][i - 1]);
}
}
lg[1] = 0;
for (int i = 2 ; i <= n ; i ++)
{
lg[i] = lg[i / 2] + 1;
}
}
int querymax(int l,int r)
{
int s = lg[r - l + 1];
return std :: max(f[l][s],f[r-(1 << s) + 1][s]);
}
int querymin(int l,int r)
{
int s = lg[r - l + 1];
return std :: min(g[l][s],g[r-(1 << s) + 1][s]);
}
void solve()
{
int l,r;
std :: cin >> l >> r;
int ans = querymax(l,r) - querymin(l,r);
std :: cout << ans << "\n";
//std :: cout << querymax(l,r) << " " << querymin(l,r) << "\n";
}
int main()
{ int t;
std :: cin >> n;
std :: cin >> t;
for (int i = 1 ; i <= n ; i ++)
{
std :: cin >> h[i];
}
init();
while (t --)solve();
}