https://www.lydsy.com/JudgeOnline/status.php?user_id=williamking5
很不错的一道题
第一问二分答案的套路水题
第二问DP的思想
先用nlogn 二分处理一下
这样就不用写单调队列了
最后被卡常数了
随便的优化一下过了
看样子应该是卡的我一两秒左右
挺不错的一道题
我完全靠我自己做了出来
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5,M=10007;
ll n,m;
inline void read(ll &x){char ch;bool ok;
for(ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') ok=1;
for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok) x=-x;}
ll A[N],DP1[N],DP2[N],S[N],B[N];
bool check(ll x){
ll a=0,b=1;
for(ll i=1;i<=n;++i){
if(A[i]>x)
return 0;
if(A[i]+a>x){
a=A[i];
++b;
}
else
a+=A[i];
}
return b-1<=m;
}
int main(){
// freopen("D://abc.txt", "r", stdin);
cin>>n>>m;
for(ll i=1;i<=n;++i)
read(A[i]);
for(ll i=1;i<=n;++i)
S[i]=S[i-1]+A[i];
ll l=0,r=1e8;
while(l<r){
ll mid=(l+r)/2;
if(check(mid))
r=mid;
else
l=mid+1;
}
cout<<l<<" ";
ll ans=l;
for(ll i=1;i<=n;++i){
l=0,r=i-1;
while(l<r){
ll mid=(l+r)/2;
if(S[i]-S[mid]<=ans)
r=mid;
else
l=mid+1;
}
B[i]=max(1ll*0,l-1);
}
for(ll i=1;i<=n;++i){
if(S[i]>ans) break;
DP1[i]++;
}
ans=DP1[n];
for(ll i=1;i<=n;++i)
DP1[i]+=DP1[i-1];
for(ll i=1;i<=m;++i){
if(i&1){
for(ll j=1;j<=n;++j){
DP2[j]=(DP1[j-1]-DP1[B[j]]+DP2[j-1]+M)%M;
}
ans=(ans+DP2[n]-DP2[n-1]+M)%M;
}
else{
for(ll j=1;j<=n;++j){
DP1[j]=(DP2[j-1]-DP2[B[j]]+DP1[j-1]+M)%M;
}
ans=(ans+DP1[n]-DP1[n-1]+M)%M;
}
}
cout<<ans<<endl;
}