題目描述
有一排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]);
}
}