●BZOJ 3831 [Poi2014]Little Bird
阿新 • • 發佈:2017-12-25
space body read off pos blank getch class esp
題解: 單調隊列優化DP 定義 F[i] 為到達第i課樹的疲勞值。 顯然最暴力的轉移就是枚舉i位置前面的k個位置,找到最優的位置跳過來。 每一個詢問的復雜度 O(KN),最壞達到O(N²)。 考慮優化: 設H為高度的話,對於兩個轉移來源位置x,y(x<y),如何如何判斷那個更優呢? 有如下4種情況: 1).H[y]≥H[x]且F[y]≤F[x],則任何時候選擇y都不會比選擇x差,所以從單調隊列裏去掉x。 2).H[y]≥H[x]且F[y]>F[x],在 x 由於距離原因而出隊之前,選擇x都不會比選擇y差,所以把y放在隊尾。
3).H[y]<H[x]且F[y]<F[x],則任何時候選擇y都不會比選擇x差,所以從單調隊列裏去掉x。
4).H[y]<H[x]且F[y]≥F[x],在 x 由於距離原因而出隊之前,選擇x都不會比選擇y差,所以把y放在隊尾。
然後用單調隊列維護就可以啦,每一個詢問的復雜度O(N)。
代碼:
題鏈:
http://www.lydsy.com/JudgeOnline/problem.php?id=3831題解: 單調隊列優化DP 定義 F[i] 為到達第i課樹的疲勞值。 顯然最暴力的轉移就是枚舉i位置前面的k個位置,找到最優的位置跳過來。 每一個詢問的復雜度 O(KN),最壞達到O(N²)。 考慮優化: 設H為高度的話,對於兩個轉移來源位置x,y(x<y),如何如何判斷那個更優呢? 有如下4種情況: 1).H[y]≥H[x]且F[y]≤F[x],則任何時候選擇y都不會比選擇x差,所以從單調隊列裏去掉x。 2).H[y]≥H[x]且F[y]>F[x],在 x 由於距離原因而出隊之前,選擇x都不會比選擇y差,所以把y放在隊尾。
#include<cstdio> #include<cstring> #include<iostream> #define MAXN 1000500 using namespace std; int H[MAXN],F[MAXN]; int N,Q; void read(int &x){ static int f; static char ch; x=0; f=1; ch=getchar(); while(ch<‘0‘||‘9‘<ch){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} x=x*f; } bool off(int x,int y){ if(H[y]>=H[x]){ if(F[y]<=F[x]) return 1; else return 0; } else{ if(F[y]<F[x]) return 1; else return 0; } } int main(){ static int pos[MAXN],l,r; read(N); for(int i=1;i<=N;i++) read(H[i]); read(Q); for(int q=1,k;q<=Q;q++){ read(k); l=1; r=0; F[1]=0; pos[++r]=1; for(int i=2;i<=N;i++){ while(l<=r&&i-pos[l]>k) l++; F[i]=F[pos[l]]+(H[pos[l]]<=H[i]); while(l<=r&&off(pos[r],i)) r--; pos[++r]=i; } printf("%d\n",F[N]); } return 0; }
●BZOJ 3831 [Poi2014]Little Bird