其他分享
首页 > 其他分享> > [HAOI2008] 木棍分割 - dp,前缀和,双指针

[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;
}

标签:cnt,const,前缀,int,sum,long,1e9,dp,HAOI2008
来源: https://www.cnblogs.com/mollnn/p/12389473.html