其他分享
首页 > 其他分享> > 7.18 T2 砍树

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