POI2014 Little Bird

Little Bird

POI2014

题意

1.有一排n棵树,第i棵树的高度是D[i]。

2.有m只小鸟要从第1棵树到第n棵树

3.如果第j只小鸟当前在第i棵树,那么它可以跳到第i+1,i+2,…,i+k[j]棵树。

4.如果小鸟跳到一棵高度大于等于当前高度的树,那么它的劳累值会加一,否则不会。

5.每只鸟最少会有多少疲劳值。

1.先写一个无脑dp
定义 dp[i]:到了i位置时最少的疲劳值是多少

dp转移
dp[i]={dp[j]+(H[i]>=H[j])} (i-K<=j<i)

2.尝试优化
探索单调性
考虑两决策,j,k谁更优
①如果 dp[j]<dp[k] 那么j决策更优
因为 dp[j]+1<=dp[k]
②如果 dp[j]=dp[k],H[j]>H[k] 那么j决策更优
因为 对于k决策要费用时,j决策不一定需要费用

因此可以维护一个单调队列,令队首的决策是最优的。
1.每次先把j<i-K的决策弹掉
2.取出队首计算dp[i]
3.弹掉队尾比dp[i]不优的决策
4.把决策i放入队尾

具体代码

#include<bits/stdc++.h>
using namespace std;
const int M=1000005;
int n,m,H[M],K;
int dp[M];
struct node{
    int id,dp,H;
}q[M];
void solve() {
    int l=1,r=1;
    dp[1]=0;
    q[r++]=(node){1,0,H[1]};
    for(int i=2; i<=n; i++) {
        while(l<r&&i-q[l].id>K)l++;
        dp[i]=q[l].dp+(H[i]>=q[l].H);
        while(l<r){
            if(dp[i]<q[r-1].dp||dp[i]==q[r-1].dp&&H[i]>q[r-1].H)r--;
            else break;
        }
        q[r++]=(node){i,dp[i],H[i]};
    }
    printf("%d\n",dp[n]);
}
int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; i++) {
        scanf("%d",&H[i]);
    }
    scanf("%d",&m);
    for(int i=1; i<=m; i++) {
        scanf("%d",&K);
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值