洛谷P3509 [POI2010]ZAB-Frog

题目大意:

说在一条小溪上有n个石头,按照严格升序给出每个是石头到源头的距离。然后说有一群灰常SB的青蛙(每块石头上一只),每次它们会选择距离自己第k远的石头跳过去。(第i个石头和第j个石头的距离为abs(a[i] – a[j])),如果距离当前位置第k远的石头不止一个,那就调到距离源头更近的那个石头。问跳m次之后,最开始处在i位置上的青蛙最终会跳到哪个石头上。

输入输出样例

输入样例#1:

5 2 4
1 2 4 7 10

输出样例#1:

1 1 3 1 1

/*
    可以用一个队列来求出每个点第k远的点(神奇) 
    然后倍增处理跳2^i能到达的点,但是MLE,需要滚动数组。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 1000010
int f[maxn][20],n,k,ans[maxn];
long long a[maxn],m;
long long qread(){
    long long i=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();}
    return i;
}
int main(){
    //freopen("Cola.txt","r",stdin);
    scanf("%d%d",&n,&k);m=qread();
    for(int i=1;i<=n;i++)a[i]=qread();
    f[1][0]=k+1;
    int l=1,r=k+1;
    for(int i=2;i<=n;i++){
        while(r<n&&a[i]-a[l]>a[r+1]-a[i])l++,r++;
        f[i][0]=a[i]-a[l]>=a[r]-a[i]?l:r;
    }
    for(int i=1;i<=n;i++)ans[i]=i;
    for(int j=1;m;j++,m>>=1)
        for(int i=1;i<=n;i++){
            if(m&1)ans[i]=f[ans[i]][(j&1)^1];
            f[i][j&1]=f[f[i][(j&1)^1]][(j&1)^1];
        }
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);
}
原文地址:https://www.cnblogs.com/thmyl/p/7467970.html