2019牛客多校第六场 D Move

传送门:https://ac.nowcoder.com/acm/contest/886/D

这题开场0/100+....然后我让byf写了先别交,然后我写完B后再去看他的代码,发现这题不就是个sb二分吗。。。不过肯定不是,不然为撒这么多人WA

后来想了想发现不是单调的,所以二分时候需要找一段区间,最后求答案也要向下找一段区间,本来以为调参要调很久,本来是每次向下找50个,最后向下找1000个,结果超时了,改成二分向下找25个,最后找100个就过了。

#include
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

s; set

:: 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>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); } }

 

你可能感兴趣的:(二分,玄学)