POI2014 Little Bird
阿新 • • 發佈:2018-12-12
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]
因為 對於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;
}