1044: [HAOI2008]木棍分割

本文介绍了一个关于木棍分割的问题,通过二分查找确定最大段的最短长度,并使用动态规划计算满足条件的方案数量。文章详细展示了算法的优化过程,从原始的O(n^2m)时间复杂度优化到O(nm)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

题目大意:有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 可以砍最多m次,要求长度最大的一段长度最小, 并求此时的方案数

题解:第一问显示是二分+贪心检验
考虑第二问

f[i][j]表示前i个分成j块满足条件的方案数

f[i][j]=ki1f[k][j1],(sum[i]sum[k]len)

这样空间是 O(nm),O(n2m) ,需要优化

空间:
f[i][j]f[i][j1]f[i]i

同时需要预处理: if(sum[i]len)f[i]=1;

空间复杂度 O(n)

时间:
观察优化后的转移式
f[i]=ki1f[k],(sum[i]sum[k]len)
容易看出满足条件的k是一段连续区间,这提示我们可以使用前缀和加速转移
设对于i,满足条件的第一个k的值为 pre[i]
发现随着i的增大k也在增大,于是利用单调性可以轻松地 O(n) 预处理出 pre[i]

用sum[i]表示li[i]的前缀和,S表示f[i]的前缀和

f[i]=S[i1]S[pre[i]1]

时间复杂度 O(nm)

我的收获:优化的思想强啊

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define P 10007
const int M=50005;

int n,m,mx,len,ans;
int li[M],sum[M];
int f[M],pre[M],S[M];

bool check(int x)
{
    int cnt=0,now=0;
    for(int i=1;i<=n;i++){
        if(now+li[i]>x){
            cnt++;
            if(cnt>m) return false;
            now=0;
        }
        now+=li[i];
    }
    return true;
}

void solve1()
{
    for(int l=mx,r=sum[n];l<=r;){
        int mid=(l+r)>>1;
        if(check(mid)) len=mid,r=mid-1;
        else l=mid+1;
    }
}

void solve2()
{
    for(int tmp=0,i=1;i<=n;i++){
        while(sum[i]-sum[tmp]>len) tmp++;
        pre[i]=tmp;
    }
    for(int i=1;i<=n&&sum[i]<=len;i++) f[i]=1;
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++) S[j]=(S[j-1]+f[j])%P;
        for(int j=1;j<=n;j++) f[j]=(S[j-1]-S[pre[j]-1]+P)%P;
        ans=(ans+f[n])%P;
    }
    ans=(ans+P)%P;
}

void work()
{
    solve1();
    solve2();
    printf("%d %d\n",len,ans);
}

void init()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) scanf("%d",&li[i]),sum[i]=sum[i-1]+li[i],mx=max(mx,li[i]);
}   

int main()
{
    init();
    work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值