제출 #1325782

#제출 시각아이디문제언어결과실행 시간메모리
1325782sh_qaxxorov_571전선 연결 (IOI17_wiring)C++20
0 / 100
30 ms10044 KiB
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;

/**
 * Maryamga simlar loyihasini ishlab chiqishda yordam beruvchi funksiya.
 * Har bir nuqta kamida bitta qarama-qarshi rangli nuqtaga ulanishi shart.
 */
ll min_total_length(vector<int> r, vector<int> b) {
    int n = r.size();
    int m = b.size();
    
    // Barcha nuqtalarni birlashtirib, tartiblaymiz
    struct Point {
        int pos, type;
    };
    vector<Point> p;
    int i = 0, j = 0;
    while (i < n || j < m) {
        if (i < n && (j == m || r[i] < b[j])) {
            p.push_back({r[i++], 0}); // 0 - qizil
        } else {
            p.push_back({b[j++], 1}); // 1 - ko'k
        }
    }

    int total_n = p.size();
    // Nuqtalarni bir xil rangli guruhlarga ajratamiz
    vector<vector<int>> groups;
    if (total_n > 0) {
        vector<int> cur = {p[0].pos};
        for (int k = 1; k < total_n; k++) {
            if (p[k].type == p[k-1].type) {
                cur.push_back(p[k].pos);
            } else {
                groups.push_back(cur);
                cur = {p[k].pos};
            }
        }
        groups.push_back(cur);
    }

    int num_groups = groups.size();
    vector<ll> dp(total_n + 1, 0);
    vector<ll> pref(total_n + 1, 0);
    for (int k = 0; k < total_n; k++) pref[k+1] = pref[k] + p[k].pos;

    // dp[i] - i-chi nuqtagacha bo'lgan minimal xarajat
    int last_idx = 0;
    vector<ll> prev_dp;

    for (int g = 0; g < num_groups; g++) {
        int cur_sz = groups[g].size();
        int first_idx = last_idx;
        last_idx += cur_sz;

        if (g == 0) {
            for (int k = 1; k <= cur_sz; k++) dp[k] = 1e18; // Birinchi guruhni bog'lab bo'lmaydi
            prev_dp.assign(dp.begin(), dp.begin() + cur_sz + 1);
            continue;
        }

        int prev_sz = groups[g-1].size();
        int p_end = first_idx - 1; 
        int c_start = first_idx;

        // DP o'tishlarini optimallashtirish uchun yordamchi massivlar
        vector<ll> cost_left(prev_sz + 1), cost_right(prev_sz + 1);
        
        for (int j = 0; j <= prev_sz; j++) {
            ll val = dp[first_idx - j];
            ll s = pref[first_idx] - pref[first_idx - j];
            ll dist_to_gap = (ll)j * p[c_start].pos - s;
            cost_left[j] = val + dist_to_gap;
            
            ll dist_to_prev_end = (ll)j * p[p_end].pos - s;
            cost_right[j] = val + dist_to_prev_end;
        }

        vector<ll> min_left(prev_sz + 2, 1e18), min_right(prev_sz + 2, 1e18);
        for (int j = prev_sz; j >= 0; j--) min_left[j] = min(min_left[j+1], cost_left[j]);
        for (int j = 0; j <= prev_sz; j++) min_right[j+1] = min(min_right[j], cost_right[j]);

        ll cur_pref_sum = 0;
        for (int i = 1; i <= cur_sz; i++) {
            cur_pref_sum += p[c_start + i - 1].pos;
            ll s_curr = cur_pref_sum - (ll)i * p[c_start].pos;
            
            // i va j ulanishlari: j >= i yoki j < i holatlari
            ll opt1 = min_left[i] + s_curr;
            ll opt2 = min_right[i] + s_curr + (ll)i * (p[c_start].pos - p[p_end].pos);
            
            dp[first_idx + i] = min(opt1, opt2);
        }
    }

    return dp[total_n];
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...