猴子

题目描述

有Q只猴子要从第一棵树到第n棵树去,第i只猴子一次跳跃的最远距离为Ki。如果它在第x棵树,那它最远可以跳到第x+Ki棵树。如果第j棵树的高度比第i棵树高或相等,那么它从第i棵树直接跳到第j棵树,它的劳累值会增加1。所有猴子一开始在第一棵树,请问每只猴子要跳到第n棵树花费的劳累值最小。

输入

第一行一个整数n,表示有n棵树。(2<=n<=1000000)

接下来第二行给出n个正整数D1,D2,……,Dn(1<=Di<=10^9),其中Di表示第i棵树的高度。

第三行给出了一个整数Q(1<=Q<=25),接下来Q行,给出了每只猴子一次跳跃的最远距离Ki(1<=Ki<=N-1)。

输出

输出Q行,每行一个整数,表示一只猴子的最小的劳累值。

样例输入

9
4 6 3 6 3 7 2 6 5
2
2
5

样例输出

2
1

题解 

设f[i][j]:第i只猴子跳到第j棵树的最小劳累值

可以得到

f [ i ][ j ] = min( f[ i ][ ii ] + (d[ j ]  >=  d[ ii ] ) )    //  ii  =  j  -  k[ i ]; ii  <  j;ii ++

再想一想,如果 f[ i ][ jj ]为最小值,那么就算h[i] > h[jj] ,f[ i ][ jj ] + 1 也一定是最小的(可能f[ i ][ jj ] 等于f[i][iii],f[ i ][ jj ] + 1 > f[i][iii],但处理一下就可以了),所以先可以不考虑是否+1,所以可以用一个单调上升序列(s)。因为队头是最小的,所以f[i][j] = f[s[head]] + (h[j] >= h[s[head]]) 。再将f[i][j]进入队列,但这里需要特殊处理一下,如果f[i][j]==f[s[tail]] && h[j] > h[s[tail]]也可将s[tail]踢出序列

参考代码:
 

for(i = 1;i <= q;i++){
    memset(s,0,sizeof s);
    head = tail = 1;
    f[i][1] = 0;
    s[1] = 1;
    for(j = 2;j <= n;j++){
        while(s[head] < j - k[i] && head < tail)
            head++;
        f[i][j] = f[i][s[head]];
        if (h[j] >= h[s[head]])
            f[i][j]++;
        while((f[i][j]<f[i][s[tail]]||(f[i][j]==f[i][s[tail]]&&h[j]>h[s[tail]]))&&head<tail)
            tail--;
        s[++tail] = j;
    }
    printf("%d\n",f[i][n]);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值