jzoj3083. 【NOIP2012模拟11.1】塔(加强)

题目

玩完骰子游戏之后,你已经不满足于骰子游戏了,你要玩更高级的游戏。
今天你瞄准了下述的好玩的游戏:
首先是主角:塔。你有N座塔一列排开。每座塔各自有高度,有可能相等。 这个游戏就不需要地图了。你每次可以选择相邻的两座塔合并在一起,即这两座塔的 高度叠加后变成了同一座塔。然后原本分别与这两座塔相邻的塔变得与这座新的塔相
邻。 你的目标是在使用最少的操作次数在游戏的最后获得一列塔,这些塔的高度从左
到右形成一个不下降的数列。

Input
第一行一个整数N。
第二行N个整数,从左到右描述塔的高度Ai。
Input
第一行一个整数N。
第二行N个整数,从左到右描述塔的高度Ai。

Sample Input
5
8 2 7 3 1
Sample Output
3

Hint
对于100%的数据 1<=N,Ai<=10^6

分析

n^2的DP很显然,用f[i]表示前i个单调的最小步数,g[i]表示在保证f[i]最小情况下的最小最后塔高度。我们可以优化下,把g[i]用单调队列维护即可。

代码

#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
long long n,l,r,a[1000005],b[1000005],f[1000005][2],d[1000005];
int main()
{
    scanf("%lld",&n);
    for (int i=1;i<=n;i++) 
    {
        scanf("%d",&a[i]);
        b[i]=b[i-1]+a[i];
    }
    d[l==r==1]=0;
    for (int i=1;i<=n;i++)
    {
        while (f[d[l+1]][1]+b[d[l+1]]<=b[i] && l<r) l++;
        f[i][0]=f[d[l]][0]+i-d[l]-1;
        f[i][1]=b[i]-b[d[l]];
        while(l<=r && f[d[r]][1]+b[d[r]]>=f[i][1]+b[i]) r--;
        d[++r]=i;
    }
    printf("%lld",f[n][0]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值