【動態規劃08】bzoj3831Little Bird(dp+單調隊列)

題目描述

有一排n棵樹,第i棵樹的高度是Di。
MHY要從第一棵樹到第n棵樹去找他的妹子玩。
如果MHY在第i棵樹,那麼他可以跳到第i+1,i+2,…,i+k棵樹。
如果MHY跳到一棵不矮於當前樹的樹,那麼他的勞累值會+1,否則不會。
爲了有體力和妹子玩,MHY要最小化勞累值。

輸入輸出格式

There is a single integer N(2<=N<=1 000 000) in the first line of the standard input: the number of trees in the Byteotian Line Forest. The second line of input holds integers D1,D2…Dn(1<=Di<=10^9) separated by single spaces: Di is the height of the i-th tree.
The third line of the input holds a single integer Q(1<=Q<=25): the number of birds whose flights need to be planned. The following Q lines describe these birds: in the i-th of these lines, there is an integer Ki(1<=Ki<=N-1) specifying the i-th bird’s stamina. In other words, the maximum number of trees that the i-th bird can pass before it has to rest is Ki-1.
Your program should print exactly Q lines to the standard output. In the I-th line, it should specify the minimum number of tiresome flight legs of the i-th bird.

f[i]表示到i的最小疲勞值,轉移方程很簡單。
f[i]=min{f[j]+a[j]>=a[i]}(i-j<=k)
但是從時間複雜度上看,這樣子是絕對會爆炸的。
所以用單調隊列維護..
顯然如果消耗相同的疲勞,那麼高的樹肯定會比低的樹更好。
所以維護一個關於疲勞值的單調增隊列。
之後隨便搞一搞就出來了。

#include<bits/stdc++.h>
#define fer(i,j,n) for(int i=j;i<=n;i++)
#define far(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
const int maxn=1000010;
const int INF=1e9+7;
using namespace std;
/*----------------------------------------------------------------------------*/
inline int read()
{
    char ls;int x=0,sng=1;
    for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1;
    for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
    return x*sng;
}
/*----------------------------------------------------------------------------*/
int n,f[maxn],a[maxn],qu,q[maxn];
inline bool cmp(int x,int y)
{
    if(f[x]<f[y])return true;
    if(f[x]>f[y])return false;
    return a[x]>=a[y];
}
int main()
{
    n=read();
    fer(i,1,n)a[i]=read();
    qu=read();
    fer(i,1,qu)
    {
        int h=1,t=1;
        int k=read();
        q[t++]=1;f[1]=0;
        fer(j,2,n)
        {
            while(h<t&&j-q[h]>k)h++;
            f[j]=f[q[h]]+(a[j]>=a[q[h]]);
            while(h<t&&cmp(j,q[t-1]))t--;
            q[t++]=j;    
        }
        printf("%d\n",f[n]);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章