牛牛的战役
作者:互联网
链接ac.nowcoder.com/acm/problem/21613
其他题解除了二分答案都好他妈智...
来一个暴力题解
首先我们知道要想最大值最小;就要尽可能的平摊每个人打的怪,那么对于一个比较大的怪,他只能有你较强的兵去打,同时你较强的兵可以打各种比他若的怪。
先对兵和怪排序
我们可以倒着一个一个考虑怪的数值,看有哪兵可以打这个怪,记录\(lp\)表示之前可以打怪总兵数;\(pre\)表示这一轮能新增的可以打怪的兵;\(ans\)表示之前的最大值;为了尽可能平摊每个人打的怪,我们要让当前的怪先平摊到新增的这部分然后考虑两种情况;
1是平摊以后的最大值小于等于\(ans\)
2是平摊以后的最大值大于\(ans\)
很明显可以发现若是第二种情况,我们可以将多出\(ans\)的部分向之前的那些兵那边去补全,那么能补多少使得值还是\(ans\)呢,这时候就发现还需要记录一个\(modd\)变量表示假设每个都填满到\(ans\)后,还能空出多少个,那么我们只要考虑\(modd\)的值即可知道什么时候能把之前的都填到\(ans\),那么填好之后如果还有多出,就要除以总人数,更新\(ans\)的值
而对于1,无需更新\(ans\)的值
对于1和2,操作后都要更新modd的值
这么一个一个考虑完即可
但是我们会发现一种特殊情况,就是新的一个怪并没有更新出多的可以打的兵,那么这时候就要一个特判此种情况,新增的人又可以摊到modd上 如果多了再更新ans值(实际为情况1但是分母不能为0所以特判).
蠢人是这么写题的...
点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node{
ll b;
ll c;
}num[55];
int cmp(node x,node y){
if(x.b!=y.b)return x.b<y.b;
else return x.c>y.c;
}
ll a[55],sum[55];
int main(){
int n,m;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+n+1);
cin>>m;
for(int j=1;j<=m;j++){
cin>>num[j].b;
}
for(int j=1;j<=m;j++){
cin>>num[j].c;
}
sort(num+1,num+m+1,cmp);
if(num[m].b>a[n]){
cout<<-1<<endl;
exit(0);
}
for(int j=1;j<=m;j++){
sum[j]=sum[j-1]+num[j].c;
}
int j=m;
ll lp=0,modd=0,ans=0,res,pre,k,l,q;
while(j>0){
int pre=lower_bound(a+1,a+1+n,num[j].b)-a;//目前num_j的最前端
res=num[j].c;//新的一段的sum
pre=n-pre+1-lp;//新的一段的总人数
if(pre==0){
if(res<=modd){
modd=modd-res;
}
else{
ans=ans+(res-modd)/lp+(1-(((res-modd)%lp)==0));
if(((res-modd)%lp)==0)modd=0;
else modd=lp-((res-modd)%lp);
}
j--;
continue;
}
k=res/pre+(1-((res%pre)==0));//新的一段如不贪的答案
if(k<ans){
modd=modd+ans*pre-res;//更新modd
}
else if(k==ans){
modd=modd+ans*pre-res;//更新modd
}
else if(k>ans){
q=res-pre*ans-modd;
if(q<0){
modd=modd+ans*pre-res;
}
else{
ans=ans+q/(lp+pre)+(1-((q%(lp+pre))==0));
if((q%(lp+pre))==0)modd=0;
else modd=(lp+pre)-q%(lp+pre);
}
}
lp=lp+pre;
j--;
}
cout<<ans<<endl;
}
标签:pre,num,平摊,牛牛,int,战役,modd,ans 来源: https://www.cnblogs.com/cigarette12/p/16072504.html