题目背景
我的滑板鞋时尚时尚最时尚
回家的路上我情不自禁
摩擦 摩擦
在这光滑的地上摩擦
月光下我看到自己的身影有时很远有时很近
感到一种力量驱使我的脚步
有了滑板鞋天黑都不怕
题目描述
你在魅力之都购买了一双时尚的滑板鞋,你非常兴奋地到处摩擦!
hzwer很想问一个问题:按照你的行动方式,你从某个结点摩擦(移动)K步后能到的目的地
这显然是一个很简单的问题,但是蒟蒻hzwer总是问个不停,所以你决定写一个程序回答他的询问
输入格式
第一行两个数n,m表示结点个数和询问次数
接下来n行,第i个数一个数a[i]表示你在第i个结点的话,下一步会移动到第a[i]个结点
接下来m行,每行两个数t,k,蒟蒻hzwer询问如果你当前在第t个结点,k步之后你会到第几个节点
输出格式
m行为每次询问的结果
样例数据 1
输入 [复制]
3 2
2
3
2
1 2
2 4
输出
3
2
备注
共十个测试点,每个测试点数据规模如下所示
100%的数据:n=10^5,m=n,k<=10^18
题解
听说是一道倍增sb题但是实际上对于蒟蒻我来说一点也不简单,首先要想通倍增为什么是对的,另外算f数组的时候要注意循环顺序,不要搞错了
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline long long read()
{
long long s=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*f;
}
const int N=1e5+5;
long long f[N][70];
long long p2[N];
int main()
{
int i,j;
long long n,m;
n=read();m=read();
p2[0]=1;
for(i=1;i<=62;i++)
p2[i]=p2[i-1]<<1;
for(i=1;i<=n;i++)
f[i][0]=read();
for(i=1;i<=62;i++)
for(j=1;j<=n;j++)
f[j][i]=f[f[j][i-1]][i-1];
long long t,k;
for(i=1;i<=m;i++)
{
t=read();k=read();
for(j=62;j>=0;j--)
if(k&p2[j])
t=f[t][j];
printf("%lld\n",t);
}
return 0;
}