码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-03-01 14:40:19      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:转移   amp   com   http   image   while   复杂度   with   include   

技术图片

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

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

标签:转移   amp   com   http   image   while   复杂度   with   include   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!