二分答案。
关键在于check()的写法。
20分的写法:
check(x) 中O(n*n)的写法:直接枚举起点,一直往后加,一旦>x,就加一张菜单,如此枚举。
60分的写法:
二分加二分。用一个前缀和来优化。
check(x)中枚举起点s,设当前这一张菜单的起点为L,那么下一个起点就是sum[L]+x的前驱,可以用upper_bound()来找,然后再把找出来的那个位置减 1 ,就是下一个起点L,菜单数加 1。直到L>=s+n就停止。再把菜单数与m进行比较。
100分的写法
在20分的基础上加上一句优化。
for(int s=1;skp<=x;s++,skp+=t[s])
check
int check(LL x)
{
int tt;
LL p,skp=0;
for(int s=1;skp<=x;s++,skp+=t[s])
{
tt=1,p=t[s];
for(int i=s+1;i<s+n;i++)
{
if(p+t[i]>x)
{
p=t[i];
tt++;
}
else p+=t[i];
}
if(tt<=m) return true; //只要有成立的,就要缩小答案
}
return false;
}
见图
skp( B这一段) 如果>x,一定会在后面使用一个菜单,那么就相当于在前面时B使用菜单一样,如果这样成立的话,那么在前面枚举s是也会成立,运行到这一步,就说明前面不成立,那么现在也不会成立;
20分代码
#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
#define N 50009
using namespace std;
int n,m,t[2*N];
LL L,R,mid;
bool check(LL x)
{
int tt;
LL p;
for(int s=1;s<=n;s++)
{
tt=1,p=t[s];
for(int i=s+1;i<s+n;i++)
{
if(p+t[i]>x)
{
p=t[i];
tt++;
}
else p+=t[i];
}
if(tt<=m) return true;
}
return false;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i]);
R+=t[i],L=max(L,1ll*t[i]);
t[i+n]=t[i];
}
while(L<=R)
{
mid=(L+R)>>1;
if(check(mid)) R=mid-1;
else L=mid+1;
}
printf("%lld",L);
return 0;
}
60分代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define LL long long
#define N 50009
using namespace std;
int n,m,t[2*N];
LL L,R,mid,sum[2*N];
bool check(LL x)
{
int tt,l;
for(int s=1;s<=n;s++)
{
l=s;tt=0;
while(l<s+n)
{
l=upper_bound(sum+l,sum+s+n+1,sum[l]+mid)-sum-1;
tt++;
}
if(tt<=m) return true;
}
return false;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i]);
R+=t[i],L=max(L,1ll*t[i]);
t[i+n]=t[i];
}
for(int i=1;i<=2*n;i++) sum[i]+=sum[i-1]+t[i];
while(L<=R)
{
mid=(L+R)>>1;
if(check(mid)) R=mid-1;
else L=mid+1;
}
printf("%lld",L);
return 0;
}
100分代码
#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
#define N 50009
using namespace std;
int n,m,t[2*N];
LL L,R,mid;
int check(LL x)
{
int tt;
LL p,skp=0;
for(int s=1;skp<=x;s++,skp+=t[s])
{
tt=1,p=t[s];
for(int i=s+1;i<s+n;i++)
{
if(p+t[i]>x)
{
p=t[i];
tt++;
}
else p+=t[i];
}
if(tt<=m) return true;
}
return false;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i]);
R+=t[i],L=max(L,1ll*t[i]);
t[i+n]=t[i];
}
while(L<=R)
{
mid=(L+R)>>1;
if(check(mid)) R=mid-1;
else L=mid+1;
}
printf("%lld",L);
return 0;
}