zoukankan      html  css  js  c++  java
  • BZOJ 1233

    DP + 单调队列

    首先证明得到,高度最高的方案同时也是底部长度最小的方案。

    sum[i]为1 - i的前缀和,f[i]代表考虑i - n使得底最小的底部宽度。

    递推式 F[i]=min(sum[j-1]-sum[i-1])  j>i 且 sum[j-1]-sum[i-1]>=F[j] 易得在满足的条件下j当然是越小越好了嘛 而这样得出的方程又满足一定的单调性 这样调整之后队首就是我们要的答案啦

    又对于转移条件 f[j]<=sum[j1]sum[i1]。

    #include <bits/stdc++.h>
    //#include <unordered_map>
    using namespace std;
    typedef long long ll;
    #define N (100010)
    #define maxn (N + 10)
    const ll mod = 998244353;
    const ll INF = (1e18) + 10;
    int sum[maxn], dp[maxn], q[maxn], h[maxn];
    int main(){
        int n;scanf("%d",&n);
        for(int i = 1;i <= n;i++){
            scanf("%d",&sum[i]);sum[i] += sum[i - 1];
        } 
        int head = 0, tail = 0;
        q[head] = n + 1;sum[n + 1] = sum[n]; 
        for(int i = n;i >= 1;i--){
            while(tail < head && sum[i - 1] <= sum[q[tail + 1] - 1] - dp[q[tail + 1]]){
                tail++;
            }
            dp[i] = sum[q[tail] - 1] - sum[i - 1];
            h[i] = h[q[tail]] + 1;
            while(tail < head && sum[i - 1] - dp[i] >= sum[q[head] - 1] - dp[q[head]]){
                head--;
            }
            q[++head] = i;
        }
        printf("%d
    ",h[1]);
        return 0;
    }
  • 相关阅读:
    【转】linux下passwd命令设置修改用户密码
    【转】Linux账号管理之useradd
    shell script练习:利用日期进行文件的创建
    [转]linux之pr命令
    [转]linux之patch命令
    [转]linux之diff 命令
    [转]linux之awk命令
    【转】Linux之printf命令
    Linux egrep命令
    [转]sed常用命令总结
  • 原文地址:https://www.cnblogs.com/cleanerhgf/p/12078125.html
Copyright © 2011-2022 走看看