传送门:https://ac.nowcoder.com/acm/contest/886/D
这题开场0/100+....然后我让byf写了先别交,然后我写完B后再去看他的代码,发现这题不就是个sb二分吗。。。不过肯定不是,不然为撒这么多人WA
后来想了想发现不是单调的,所以二分时候需要找一段区间,最后求答案也要向下找一段区间,本来以为调参要调很久,本来是每次向下找50个,最后向下找1000个,结果超时了,改成二分向下找25个,最后找100个就过了。
#include<bits/stdc++.h>
using namespace std;
int v[1005];int n,k;
struct p{
int x;
p(){}
p(int x):x(x){}
friend bool operator<(p a,p b)
{
return a.x>b.x;
}
}pp[1005];
set<p> s;
set<p> :: iterator it;
int num[1006];
bool check(int vol)
{
int tol=k,d;
s.clear();
for(int i=1;i<=n;i++)
{
if(num[pp[i].x]==0)
s.insert(pp[i]);
num[pp[i].x]++;
}
while(tol&& ((int)s.size())>0)
{
tol--;
p res(vol);
it=s.lower_bound(res);
while(it!=s.end())
{
d=(*it).x;
res.x-=d;
num[d]--;
if(num[d]==0)
s.erase(it);
it=s.lower_bound(res);
}
}
for(int i=1;i<=n;i++)
num[pp[i].x]=0;
if(s.size()>0) return false;
return true;
}
int main()
{
int t;
scanf("%d",&t);
for(int kace=1;kace<=t;kace++)
{
scanf("%d%d",&n,&k);
int r=0;
for(int i=1;i<=n;i++) scanf("%d",&v[i]),r+=v[i];
for(int i=1;i<=n;i++) pp[i].x=v[i];
int l=0,mid;
int ans=r;
bool flag;
while(l+1<r)
{
mid=(l+r)>>1;
flag=false;
for(int j=max(l+1,mid-25);j<=mid;j++)
if(check(j))
flag=true;
if(flag)
r=mid;
else
l=mid;
}
for(int j=max(1,r-100);j<=r;j++)
if(check(j))
{
ans=j;
break;
}
printf("Case #%d: %d\n",kace,ans);
}
}