7.18 T2 砍树
作者:互联网
题解:
一开始一看就码了一个二分,然而二分的左右端点又写错了,导致20分直接丢掉,挺难受的。
这个题不能二分,因为不满足单调性(不信的话可以输出一下search函数的返回值,发现是0101000111。。之类的)。
说正解,需要砍掉的长度tot=Σ[a[i]/d]×d-Σa[i],要求tot<=k;另sum=k+Σa[i],得Σ[a[i]/d]×d<=sum,移项Σ[a[i]/d]<=sum/d;左边的是分段函数而且单调递减,d是从小到大枚举,递增的,除过去递减的,但左边减的快,右边慢,(画图理解)。因为sum/d是向下取整的,所以是分段递减,左边是l的话,r=sum/(sum/l);原谅我也不知道这是为什么。。。只需要判断d=r是否满足Σ[a[i]/d]×d<=sum的条件,满足就更新ans,不满足就下一个。为啥是右端点呢?第一是因为题目要求d最大,右端点就是最大的。第二就是Σ[a[i]/d]是单调递减的,而sum/d是平的,右端点不符合那整段就一定不符合了。
这题很可惜,二分的错解范围打错直接爆0,丢了20分,血的教训啊!!!
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; ll n,k,a[250],mm,ans,sum,d; bool vis[250]; ll max(ll x,ll y){ return x>y?x:y; } inline ll read() { register ll aa=0,bb=1;char cc=getchar(); while(cc>'9'||cc<'0'){if(cc=='-') bb=-1;cc=getchar();} while(cc<='9'&&cc>='0'){aa=aa*10+cc-'0';cc=getchar();} return aa*bb; } int main() { n=read();k=read(); for(register int i=1;i<=n;i++){ a[i]=read(); mm=max(a[i],mm); sum+=a[i]; } sum+=k; while(1){ if(sum/(d+1)<=0) break; d=sum/(sum/(d+1)); ll tot=0; for(int i=1;i<=n;i++){ tot+=a[i]/d; if(a[i]%d) tot++; } if(d*tot<=sum) ans=d; } printf("%lld\n",ans); return 0; }View Code
标签:aa,二分,cc,T2,ll,7.18,read,砍树,include 来源: https://www.cnblogs.com/jrf123/p/11209649.html