[HAOI2008] 木棍分割 - dp,前缀和,双指针

Solution

第一问二分模板题,利用第一问答案做第二问
\(O(n^2m)\) 的 dp 是显然的,考虑用前缀和优化,用双指针预处理出转移位置的边界,于是每次转移复杂度 \(O(1)\),总体复杂度 \(O(nm)\)

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 10007;
const int N = 50005;

int n,m,l[N],f[N],g[N],s[N],p[N];

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>l[i];
    int L=0,R=1e9;
    while(L<R) {
        int mid=(L+R)/2;
        int cnt=0,sum=1e9;
        for(int i=1;i<=n;i++) {
            if(sum+l[i]>mid) {
                sum=0;
                cnt++;
            }
            sum+=l[i];
            if(sum>mid) cnt=1e9;
        }
        if(cnt<=m+1) R=mid;
        else L=mid+1;
    }
    int ans=L;
    for(int i=1;i<=n;i++) s[i]=s[i-1]+l[i];
    int pos=1;
    for(int i=1;i<=n;i++) {
        while(s[i]-s[pos]>ans && pos<i) ++pos;
        p[i]=pos;
    }
    int aans=0;
    for(int i=1;i<=n;i++) if(s[i]<=ans) g[i]=1;
    for(int i=2;i<=m+1;i++) {
        for(int j=1;j<=n;j++) g[j]+=g[j-1], g[j]%=mod;
        for(int j=1;j<=n;j++) f[j]=g[j-1]-g[p[j]-1], f[j]+=mod, f[j]%=mod;
        for(int j=1;j<=n;j++) g[j]=f[j];
        aans+=f[n];
        aans%=mod;
    }
    cout<<ans<<" "<<aans;
}

原文地址:https://www.cnblogs.com/mollnn/p/12389473.html

时间: 2024-08-30 13:26:45

[HAOI2008] 木棍分割 - dp,前缀和,双指针的相关文章

bzoj1044[HAOI2008]木棍分割 单调队列优化dp

1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4314  Solved: 1664[Submit][Status][Discuss] Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果

1044: [HAOI2008]木棍分割

1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2161  Solved: 779[Submit][Status][Discuss] Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果m

[HAOI2008]木棍分割解题报告

305 . [HAOI2008] 木棍分割 ★★★☆ 输入文件:stick.in 输出文件:stick.out 简单对比 时间限制:3 s 内存限制:64 MB [问题描述] 有n根木棍,第i根木棍的长度为Li,n根木棍依次连结在一起,总共有n-1个连接处.现在允许你最多砍断m个连接处,砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小,并且输出有多少种砍木棍的方法使得总长度最大的一段长度最小. [输入格式] 输入文件第一行有2个数n,m 接下来n行每行一个正整数Li,表示第i根木棍

BZOJ1044: [HAOI2008]木棍分割

1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1580  Solved: 567[Submit][Status] Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007.

bzoj1044 [HAOI2008]木棍分割——前缀和优化DP

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1044 咳咳...终于A了... 居然没注意到正着找pos是n方会TLE...所以要倒着找pos: 二分还写错了,改了半天... 小心前缀和取模后相减变成负数!!!!!!!!! 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn

【bzoj1044】[HAOI2008]木棍分割 二分+dp

题目描述 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007... 输入 输入文件第一行有2个数n,m.接下来n行每行一个正整数Li,表示第i根木棍的长度.n<=50000,0<=m<=min(n-1,1000),1<=Li<=1000. 输出 输出有2个数,

【BZOJ】1044: [HAOI2008]木棍分割 二分+区间DP

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1044 Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007... Input 输入文件第一行有2个数n,m. 接下来n行每行一个正整数Li,表示第i根木棍

bzoj 1044 [HAOI2008]木棍分割(二分+贪心,DP+优化)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1044 [题意] n根木棍拼到一起,最多可以切m刀,问切成后最大段的最小值及其方案数. [思路] 对于第一问可以二分后贪心判断. 假设第一问得到的答案为L,设f[i][j]前i个木棍切j下且保持段长不超过L的方案数,则有转移式: f[i][j]=sigma { f[k][j-1] },k<i,suma(k+1,i)<=L 优化:  空间方面可以用个滚动数组. 时间方面由于前缀和sum

bzoj 1044: [HAOI2008]木棍分割

2016-06-20 第一问是个二分的经典入门题 第二问很容易发现一个DP f[i][j]前i个木棍分j次合法方案数,f[i][j]=f[k][j-1]+...+f[i-1][j-1]; 但这样时间复杂度是O(mn^2),空间复杂度是O(mn) 但我们发现对于相同的j随着i的增加,对应的k也增加,那我们可以根据这个单调性,用前缀和来做到转移复杂度为O(1),空间可以用滚动数组来解决,本来我偷懒用short int开数组,不用滚动数组.结果T了一半,早就听说数组大了会使程序变慢,今天我可算知道了,