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;
}
posted @ 2026-10-21 21:06  elon_giao  阅读(4)  评论(0)    收藏  举报