POI2014Little Bird

首先要想到dp,那么定义dp[i]为走到第i棵树时的最少劳累值.

那么dp转移的时候就要考虑到两点之间的高度大小关系,所以要分类讨论.

那么这样的dp就是 O(n2) 的了.

所以考虑优化,因为我们发现一个点的dp值只可能够由它的前k个来转移,所以想到使用单调队列来优化dp.

然后什么样的值才是最优的呢?

首先dp值小的一定更优!

因为dp值只能够一个一个地发生变化,所以无论高度差如何,只要dp值小1,它就可以通过1的代价使得高度升高.

然后就是高度的差别了,相同的dp值的情况,高度高的肯定更优,因为它有更大的空间去选择,即相同的高度,它的dp值不增加的可能性更大.

然后用单调队列来优化一下就行了…

#include
#include
#include
#include
#define M 1000005
using namespace std;
void Rd(int &res){
    res=0;char p;
    while(p=getchar(),p<'0');
    do{
        res=(res<<1)+(res<<3)+(p^48);
    }while(p=getchar(),p>='0');
}
int q[M],dp[M],H[M],n,m;
bool Better(int x,int y){
    if(dp[x]return true;
    else if(dp[x]>dp[y])return false;
    return H[x]>=H[y];
}
int main(){
    Rd(n);
    for(int i=1;i<=n;i++)Rd(H[i]);
    Rd(m);
    for(int i=1;i<=m;i++){
        int k,l=0,r=0;Rd(k);
        q[r++]=1,dp[1]=0;
        for(int j=2;j<=n;j++){
            while(lk)l++;
            dp[j]=dp[q[l]]+(H[j]>=H[q[l]]);
            while(l1]))r--;
            q[r++]=j;
        }
        printf("%d\n",dp[n]);
    }
    return 0;
}

你可能感兴趣的:(poi,---单调队列)