又是一道单调队列优化dp的题目 这道题呢 先要了解一个结论,在多种可行的堆叠方案中,至少有一种能使层数最高的方案同时使得底边最短。即底边最短的,层数一定最高。 这个是zkw大神得出的 我也不会证明来着 反正这样之后我们就可以得出正确的方法了

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

又对于转移条件 

剩下的看看代码吧

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=100007;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
} 
int f[M],g[M],sum[M],q[M],head,tail,n,w;
int main()
{
    n=read();
    for(int i=1;i<=n;i++) w=read(),sum[i]=sum[i-1]+w;
    q[0]=n+1;
    for(int i=n;i;i--){
        while(head<tail&&sum[q[head+1]-1]-sum[i-1]>=f[q[head+1]]) head++;
        f[i]=sum[q[head]-1]-sum[i-1];
        g[i]=g[q[head]]+1;
        while(head<tail&&f[i]-sum[i-1]<=f[q[tail]]-sum[q[tail]-1]) tail--;
        q[++tail]=i;
    }
    printf("%d\n",g[1]);
    return 0;
}
View Code

相关文章:

  • 2022-12-23
  • 2021-09-29
  • 2021-08-18
  • 2021-08-05
  • 2022-12-23
  • 2021-09-23
  • 2022-12-23
  • 2022-02-26
猜你喜欢
  • 2021-10-07
  • 2022-02-05
  • 2021-11-10
  • 2022-03-03
  • 2022-03-09
  • 2021-11-10
相关资源
相似解决方案