luogu P7287 「EZEC-5」魔法
作者:互联网
题面传送门
挺好的一道题。
首先一个很明显的贪心:先加后乘,这样一定最大。
然后又注意到,在最大子段和为正时,第二个操作的使用次数不会超过\(logs\)次。
所以可以枚举第二个操作的执行次数。
那么第一个操作显然是在刚好的时候最优,这个用二分可以轻松解决。
时间复杂度\(O(nlog^2s)\)
代码实现:
#include<cstdio>
#define ll long long
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int n,m,k,x,y,z;
long long s,a[100039],b[100039],ans=1e18,now=1,pus,tot,l,r,mid;
inline int check(long long mid){
register int i;
for(i=1;i<=n;i++) a[i]+=mid;
tot=pus=0;
for(i=1;i<=n;i++){
tot+=a[i];
if(tot<0)tot=0;
pus=max(pus,tot);
}
for(i=1;i<=n;i++) a[i]-=mid;
return pus?((s+pus-1)/pus<=now):0;
}
int main(){
freopen("1.in","r",stdin);
register int i,j;
scanf("%d%d%d%lld",&n,&m,&k,&s);
for(i=1;i<=n;i++) scanf("%lld",&a[i]);
for(i=0;i<=35;i++){
l=-1;r=2e9;
while(l+1<r){
mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid;
}
ans=min(ans,(ll)i*k+(ll)r*m);
now<<=1;
}
printf("%lld\n",ans);
}
标签:int,luogu,ll,ans,mid,long,P7287,EZEC,check 来源: https://www.cnblogs.com/275307894a/p/14352107.html