[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