1. 程式人生 > >Bzoj 3831: [Poi2014]Little Bird

Bzoj 3831: [Poi2014]Little Bird

元素 eof ont pac color can 16px set 題目

3831: [Poi2014]Little Bird

題目大意:從1開始,跳到比當前矮的不消耗體力,否則消耗一點體力,每次詢問有一個步伐限制,求每次最少耗費多少體力

f[i]表示跳到i位置消耗的最小體力

從單調隊列中取數,維護的東西有三個

1.單調隊列的範圍維持在K以內

2.隊列尾部位置對應的答案與當前枚舉到的位置對應的答案相比,當前答案更優時(f[now]最小時),彈出尾元素

3.隊列尾部位置對應的答案與當前枚舉到的位置對應的答案相同時,比較當前位置的高度和隊尾位置的高度,隊尾元素較低的話,彈出尾元素

一系列維護之後,將當前點放入隊尾

#include<iostream>
#include
<cstdio> #include<cstring> using namespace std; int n,m,q[1000010],H[1000010],f[1000010]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&H[i]); scanf("%d",&m); int h,t; for(int j=1;j<=m;j++){ h=t=1; int k;scanf("%d",&k); memset(q,
0,sizeof(q)); memset(f,0,sizeof(h)); q[t++]=1; for(int i=2;i<=n;i++){ while(h<t&&i>q[h]+k)h++; f[i]=f[q[h]]+(H[q[h]]>H[i]?0:1); while(h<t&&(f[q[t-1]]>f[i]||(f[q[t-1]]==f[i]&&H[q[t-1]]<=H[i])))t--; q[t
++]=i; } printf("%d\n",f[n]); } }

Bzoj 3831: [Poi2014]Little Bird