【讲题用】超时空彩叶姬 题解

题

Description

一共 \(n\) 周。

初始:\(cash=0\),\(coin=0\)

每周彩叶:

  • 先获得 \(b_i\) 元。
    \(cash \leftarrow cash+b_i\)

  • 然后把其中任意一部分兑换为福币(可以全换或不换),\(1\) 元可以兑换 \(a_i\) 福币。
    \(cash \leftarrow cash - c_i\),\(coin \leftarrow coin + c_i a_i\)

  • 再消费固定的 \(x\) 福币。
    \(coin \leftarrow coin - x\)

之前没用完的日元和福币可以接着用。

求最大可能 \(x\)。

Solution

\(x\) 越大越难满足要求,答案具有单调性,于是二分。

二分关键在于两点:值域和 check 函数。

值域:\([1,a_1 b_1]\)。

check:贪心。

  • 若今后没有 \(a_i\) 更大的周,那就把 \(cash\) 全换成 \(coin\)。

  • 若今后有 \(a_i\) 更大的周,设离当今最近的是第 \(j\) 周,那么尽可能换够直至第 \(j-1\) 周所需的 \(coin\)。

接下来问题是如何得到 \(j\) 的值。醋:单调栈。

Code

#include <bits/stdc++.h>
typedef long long i64;
using namespace std;

const i64 INF = LLONG_MAX;
const int MAXN = 2e6;

i64 ceil_div(i64 a, i64 b) {
    return (a + b - 1) / b;
}

int n;
i64 a[MAXN + 1], b[MAXN + 1], p[MAXN + 1]; // p[i] 下一个更划算的周

bool isLegal(i64 x) {
    i64 cash = 0, coin = 0;
    for (int i = 1; i <= n; ++i) {
        cash += b[i];
        if (p[i] == 0) {
            coin += cash * a[i];
            cash = 0;
        }
        else {
            i64 need = (p[i] - i) * x;
            if (coin < need) {
                i64 lack = need - coin; // 不要忘记已有的币
                i64 buy = min(ceil_div(lack, a[i]), cash);
                coin += buy * a[i];
                cash -= buy;
            }
        }
        coin -= x;
        if (coin < 0)
            return false;
    }
    return true;
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; ++i)
        cin >> a[i];
    for (int i = 1; i <= n; ++i)
        cin >> b[i];

    stack<int> st;
    for (int i = n; i >= 1; --i) { // 从后往前跑单调栈
        while (!st.empty() && a[i] >= a[st.top()])
            st.pop();
        p[i] = st.empty() ? 0 : st.top();
        st.push(i);
    }

    i64 l = 0, r = a[1] * b[1];
    while (l < r) {
        i64 mid = (l + r + 1) >> 1;
        if (isLegal(mid))
            l = mid;
        else
            r = mid - 1;
    }
    cout << l << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}
posted @ 2026-07-23 22:34  SHUddol  阅读(15)  评论(0)    收藏  举报