P7287 「EZEC-5」魔法
P7287 「EZEC-5」魔法
思路
显而易见的,先做操作 1 而且所有操作做全局。
考虑到在做完操作 1 之后,最后满足答案的一定是此时的一个最大子段和。所以考虑二分操作 1,然后发现它是单调...是斜着的台阶?
突然发现最多会使用 log 次的操作 2,所以枚举操作 2 的次数。然后再去二分操作 1 的最少次数,可以使得操作 2 的次数满足当前的枚举。然后答案取最小。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define freop(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
#define re register
#define endl '\n'
#define inf LONG_LONG_MAX
#define lb(x) ((x)&-(x))
#define pii pair<int,int>
#define fir first
#define sec second
#define mkp(a,b) make_pair(a,b)gs
const int N=1e5+1;
int n;ll A[N],s,a,b,ans=inf;
inline int che(ll x){
ll mn=0,mx=-inf,sm=0;
for(int i = 1;i<=n;++i)
sm+=A[i]+x,mx=max(mx,sm-mn),mn=min(mn,sm);
if(mx>=s) return 0;
// cerr << x << ' ' << mx << endl;
if(mx<=0ll) return 0x7f7f7f7f;
return ceil(log2(1.0*s/mx));
}
inline ll js(int x){
ll l=0,r=1e16,mid;
while(l<r){
mid=(l+r)>>1;
if(che(mid)<=x) r=mid;
else l=mid+1;
}
return l*a+x*b;
}
int main(){
cin.tie(0)->ios::sync_with_stdio(false);
cout.tie(0);
// freop();
//↑以上为初始化↑
//------------------------------
cin >> n >> a >> b >> s;
for(int i = 1;i<=n;++i) cin >> A[i];
for(int j = 0;j<=47;++j) ans=min(ans,js(j));
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号