bzoj bzoj 3831 Little Bird 單調佇列優化DP
阿新 • • 發佈:2020-09-12
bzoj 3831 Little Bird
單調佇列優化DP。
設\(f[i]\)表示從1到\(i\)的最少步數,那麼轉移方程很好想:\(f[i] = a[i] < a[h] ? f[h] : f[h] + 1\)。
主要是得用單調佇列優化,考場上我傻乎乎的寫了個線段樹優化,時間根本沒降下來,還挺難碼。。。
將\(f[i]\)壓入隊尾的時候,如果\(f\)值相同,那麼把更高的放進去。
#include <bits/stdc++.h> using namespace std; inline long long read() { long long s = 0, f = 1; char ch; while(!isdigit(ch = getchar())) (ch == '-') && (f = -f); for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48)); return s * f; } const int N = 1e6 + 5, inf = 1e9; int n, m; int q[N], h[N], f[N]; void work(int k) { int l = 1, r = 1; q[1] = 1; for(int i = 2;i <= n; i++) { while(l <= r && i - q[l] > k) l++; if(h[i] < h[q[l]]) f[i] = f[q[l]]; else f[i] = f[q[l]] + 1; while(l <= r && (f[q[r]] > f[i] || (f[q[r]] == f[i] && h[q[r]] <= h[i]))) r--; q[++r] = i; } printf("%d\n", f[n]); } int main() { n = read(); for(int i = 1;i <= n; i++) h[i] = read(); m = read(); for(int i = 1, k;i <= m; i++) k = read(), work(k); fclose(stdin); fclose(stdout); return 0; }