Submission #1327587

#TimeUsernameProblemLanguageResultExecution timeMemory
1327587sh_qaxxorov_571Snowball (JOI21_ho_t2)C++20
0 / 100
1 ms332 KiB
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;

/**
 * JOI 2020/2021 Final Round - Snowball
 * Karmaşıklık: O(N + Q)
 */

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

    int N, Q;
    cin >> N >> Q;

    vector<ll> X(N);
    for (int i = 0; i < N; i++) cin >> X[i];

    vector<ll> W(Q);
    ll current_pos = 0;
    ll min_dist = 0; // Başlangıca göre ulaşılan en batı (negatif)
    ll max_dist = 0; // Başlangıca göre ulaşılan en doğu (pozitif)

    // Her günün sonunda ulaşılan maksimum batı ve doğu sınırlarını sakla
    vector<pair<ll, ll>> history;
    for (int i = 0; i < Q; i++) {
        ll w;
        cin >> w;
        current_pos += w;
        min_dist = min(min_dist, current_pos);
        max_dist = max(max_dist, current_pos);
        history.push_back({-min_dist, max_dist});
    }

    vector<ll> weight(N, 0);

    // Her kartopu çifti arasındaki kar paylaşımını hesapla
    for (int i = 0; i < N - 1; i++) {
        ll gap = X[i + 1] - X[i];
        ll left_share = 0, right_share = 0;

        // İkili arama ile bu gap'in ne zaman dolduğunu bulabiliriz 
        // veya history üzerinden doğrusal bakabiliriz (Q büyük olduğu için ikili arama daha güvenli)
        int low = 0, high = Q - 1;
        int last_day = -1;
        
        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (history[mid].first + history[mid].second >= gap) {
                last_day = mid;
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }

        if (last_day == -1) {
            // Gap hiç dolmadı
            left_share = history[Q - 1].second;
            right_share = history[Q - 1].first;
        } else {
            // Gap'in dolduğu gün kar paylaşımı
            ll L_at_last = history[last_day].first;
            ll R_at_last = history[last_day].second;
            
            // Eğer o gün rüzgar doğuya estiyse (R arttıysa)
            if (last_day > 0 && history[last_day].second > history[last_day-1].second) {
                left_share = R_at_last; // i. kartopu doğuya giderek aldı
                right_share = gap - left_share;
            } else if (last_day > 0 && history[last_day].first > history[last_day-1].first) {
                // Rüzgar batıya estiyse
                right_share = L_at_last; // i+1. kartopu batıya giderek aldı
                left_share = gap - right_share;
            } else {
                // İlk gün dolma durumu
                if (current_pos > 0) { // Doğuya
                    left_share = min(gap, history[0].second);
                    right_share = gap - left_share;
                } else {
                    right_share = min(gap, history[0].first);
                    left_share = gap - right_share;
                }
            }
        }
        weight[i] += left_share;
        weight[i + 1] += right_share;
    }

    // En uçtaki kartoplarının dışa bakan kısımlarını ekle
    weight[0] += history[Q - 1].first;
    weight[N - 1] += history[Q - 1].second;

    for (int i = 0; i < N; i++) {
        cout << weight[i] << "\n";
    }

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...