bzoj1044: [HAOI2008]木棍分割

题目
题解
f [ i ] [ j ] = Σ f [ i 1 ] [ k ] { k | s u m [ j ] s u m [ k ] <= a n s 1 }

#include<bits/stdc++.h>
using namespace std;
const int M=10007,N=50002;
int ans1,ans2,f[2][N],a[N],sum[N],n,m,q[N],i;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x=0,fl=1;char ch=gc();
    for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
    for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
    return x*fl;
}
bool check(int x){
    int cnt=0,sum=0;
    for (int i=1;i<=n;i++){
        sum+=a[i];
        if (sum>x) cnt++,sum=a[i];
        if (a[i]>x || cnt>m) return 0;
    }
    return 1;
}
void solve1(){
    int l=1,r=sum[n];
    while (l<=r){
        int mid=l+r>>1;
        if (check(mid)) ans1=mid,r=mid-1;
        else l=mid+1;
    }
    printf("%d ",ans1);
}
void solve2(){
    int x1=0,x2=1,tot;
    f[0][0]=1;
    for (int i=1;i<=m;i++,x1^=1,x2^=1){
        int h=1,t=1;q[1]=0;
        tot=f[x1][0];
        for (int j=1;j<=n;j++){
            while (h<=t && sum[j]-sum[q[h]]>ans1) tot=(tot-f[x1][q[h++]]+M)%M;
            f[x2][j]=tot;q[++t]=j;
            tot=(tot+f[x1][j])%M;
        }
        for (int j=n-1;j;j--)
            if (sum[n]-sum[j]>ans1) break;
            else ans2=(ans2+f[x2][j])%M;
        f[x1][0]=0;
    }
    printf("%d",ans2);
}
int main(){
    n=read();m=read();
    for (i=1;i<=n;i++) a[i]=read(),sum[i]=sum[i-1]+a[i];
    solve1();
    solve2();
}

猜你喜欢

转载自blog.csdn.net/xumingyang0/article/details/80864810
今日推荐