bzoj1233 [Usaco2009Open]干草堆tower
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1233
【题解】
家里网络坏了一天。。。
这题有个很神奇的结论:当底层最小的时候,一定有一种方案叠得最高。
这样就可以dp了。又发现前缀和s是单调递减(从后往前),所以维护单调队列即可。
注释里面是暴力。
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, a[M], s[M], f[M], g[M], m; int q[M]; int main() { cin >> n; for (int i=1; i<=n; ++i) { scanf("%d", a+i); s[i] = s[i-1] + a[i]; } int head = 1, tail = 0; q[++tail] = n+1; for (int i=n; i>=1; --i) { /* for (int j=i+1; j<=n+1; ++j) if(s[j-1] - s[i-1] >= f[j]) { if(g[i] < g[j] + 1) { g[i] = g[j] + 1; f[i] = min(f[i], s[j-1] - s[i-1]); } } */ while(head < tail && s[q[head+1]-1] - f[q[head+1]] >= s[i-1]) ++head; f[i] = s[q[head]-1] - s[i-1]; g[i] = g[q[head]] + 1; while(head <= tail && s[q[tail]-1] - f[q[tail]] < s[i-1] - f[i]) --tail; q[++tail] = i; } cout << g[1]; return 0; }