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;
}
View Code

 

posted @ 2017-06-08 15:06  Galaxies  阅读(299)  评论(4编辑  收藏  举报