[R1D]传送

// 4. [R1D]传送.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

/*
#4. [R1D]传送
https://bs.daimayuan.top/p/4
时空限制: 1S/512M
难度: 8
提交: 1043 通过: 134

题目描述:
给定 n 个格子和一个长度为 n 的正整数数组 A1,A2,...,An,当你位于格子 i 时,下一秒你会被传送到格子 Ai。

有 q 个询问,第 i 个询问需要求如果初始位于格子 si, ci 秒后你的位置。

输入格式:
第一行包含一个正整数 n,表示格子的数量。
第二行包含 n 个正整数,分别表示位于每个格子时下一秒的传送位置。
第三行包含一个正整数 q,表示询问的数量。
接下来 q 行,每行包含两个正整数 si 和 ci,表示询问如果初始位于格子 si, ci 秒后你的位置。

输出格式:
对于每个询问,在单独的一行中输出一个整数,表示答案。

样例输入:
5
2 3 5 4 1
2
1 3
4 10086


样例输出:
5
4

数据规模:
对于 100% 的数据,1≤n,q≤2×10^5,1≤Ai,si≤n,1≤ci≤10^9。

测试点分布:
- 测试点 1~2: n≤2000, ci≤20000, q≤2×10^5
- 测试点 3: n≤2×10^5, ci≤20
- 测试点 4~5: n≤2×10^5, ci≤10
- 测试点 6~10: n≤2×10^5, ci≤10^9
*/
#include <iostream>

using namespace std;



const int N = 200010, LOG = 31;

int up[N][LOG];
int a[N];
int n, m;


void pre() {
	for (int i = 1; i <= n; i++) up[i][0] = a[i];

	//从k开始逐个点计算, 层级深一倍 每个点都计算一次
	for (int k = 1; k < LOG; k++) {
		for (int i = 1; i <= n; i++) {
			up[i][k] = up[up[i][k - 1]][k - 1];
		}
	}
}

void query(int p, int jump) {
	for (int i = 0; i < LOG; i++) {
		if ( (jump >> i)  & 1) {
			p = up[p][i];
		}
	}  
	cout << p << endl;
}


int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	pre();
	cin >> m;
	for (int i = 0; i < m; i++) {
		int p, t; cin >> p >> t;
		query(p,t);
	}

	return 0;  
}

 

posted on 2025-07-10 12:47  itdef  阅读(7)  评论(0)    收藏  举报

导航