[HAOI2008] 木棍分割 - dp,前缀和,双指针
Posted mollnn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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;
}
以上是关于[HAOI2008] 木棍分割 - dp,前缀和,双指针的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1044 [HAOI2008]木棍分割——前缀和优化DP