제출 #1355219

#제출 시각아이디문제언어결과실행 시간메모리
1355219kismisBitaro the Brave 2 (JOI25_ho_t2)C++20
100 / 100
645 ms15920 KiB
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int N;
ll A[500005], B[500005];
ll prefB[500005]; // prefB[i] = B[1]+...+B[i], prefB[0]=0

bool check(ll x) {

    // ---- Build vt1 (valid starting points j) ----
    // Sweeping i from N down to 1.
    // For monster i in the suffix phase (fighting j..N):
    //   strength when reaching i = x + prefB[i-1] - prefB[j-1]
    //   need: x + prefB[i-1] - prefB[j-1] >= A[i]
    //   => prefB[j-1] <= x + prefB[i-1] - A[i]   (threshold)
    //
    // j ranges 1..i, so j-1 ranges 0..i-1.
    // upper_bound(prefB, prefB+i, threshold) = first element > threshold in prefB[0..i-1]
    // cnt = that offset = number of valid j-1 values (0..cnt-1)
    // so maxJ(i) = cnt  (valid j values are 1..cnt)
    //
    // Track runMin = min(maxJ) over i..N seen so far.
    // When runMin == i: i is a valid starting point. Add to vt1, reset runMin.

    vector<int> vt1;
    vt1.reserve(N);
    int runMin = INT_MAX;

    for (int i = N; i >= 1; i--) {
        ll threshold = x + prefB[i-1] - A[i];

        // prefB[0..i-1] has i elements
        int cnt = (int)(upper_bound(prefB, prefB + i, threshold) - prefB);
        int maxJ = cnt; // largest j with prefB[j-1] <= threshold, j in [1..i]

        runMin = min(runMin, maxJ);

        if (runMin == i) {
            vt1.push_back(i);
            runMin = INT_MAX; // reset: next segment starts fresh
        }
    }

    reverse(vt1.begin(), vt1.end()); // sorted ascending

    if (vt1.empty()) return false;

    // j=1 means no prefix needed, suffix 1..N covers everything
    if (vt1[0] == 1) return true;

    // ---- Build vt2 (valid prefix ending indices i) ----
    // Sweeping i from 1 to N-1.
    // For monster i in the prefix phase (fighting 1..j-1 after suffix j..N):
    //   strength when reaching i = x + prefB[N] - prefB[j-1] + prefB[i-1]
    //   need: >= A[i]
    //   => prefB[j-1] <= x + prefB[N] + prefB[i-1] - A[i]   (threshold)
    //
    // j ranges 2..N, so j-1 ranges 1..N-1.
    // upper_bound(prefB+1, prefB+N, threshold) = first element > threshold in prefB[1..N-1]
    // cnt = offset from prefB+1 = number of valid j-1 values in [1..N-1]
    // valid j = 2..cnt+1, so maxJ = min(cnt+1, N)
    //
    // Find largest element in vt1 <= maxJ (bestJ).
    // Track currMin = min(bestJ) seen so far.
    // Push i to vt2 while i < currMin. Stop when i >= currMin.

    vector<int> vt2;
    vt2.reserve(N);
    int currMin = INT_MAX;

    for (int i = 1; i <= N - 1; i++) {
        ll threshold = x + prefB[N] + prefB[i-1] - A[i];

        // prefB[1..N-1] has N-1 elements
        int cnt = (int)(upper_bound(prefB + 1, prefB + N, threshold) - (prefB + 1));
        int maxJ = min(cnt + 1, N); // j in [2..cnt+1], cap at N

        // largest element in vt1 that is <= maxJ
        auto it = upper_bound(vt1.begin(), vt1.end(), maxJ);
        if (it == vt1.begin()) break; // no valid j in vt1 for this i
        --it;
        int bestJ = *it;

        currMin = min(currMin, bestJ);

        if (i < currMin) {
            vt2.push_back(i);
        } else {
            break;
        }
    }

    if (vt2.empty()) return false;

    // ---- Final check: any i in vt2 with i+1 in vt1? ----
    for (int i : vt2) {
        if (binary_search(vt1.begin(), vt1.end(), i + 1)) {
            return true;
        }
    }
    return false;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> N;
    for (int i = 1; i <= N; i++) cin >> A[i];
    for (int i = 1; i <= N; i++) cin >> B[i];

    prefB[0] = 0;
    for (int i = 1; i <= N; i++) prefB[i] = prefB[i-1] + B[i];

    ll lo = 0, hi = 1e9;
    while (lo < hi) {
        ll mid = lo + (hi - lo) / 2;
        if (check(mid)) hi = mid;
        else lo = mid + 1;
    }

    cout << lo << "\n";
    return 0;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…