제출 #1356810

#제출 시각아이디문제언어결과실행 시간메모리
1356810yogesh_saneJob Scheduling (IOI19_job)C++20
100 / 100
125 ms16688 KiB
#include <iostream>
#include <vector>
#include <queue>
#include <numeric>

using namespace std;

typedef long long ll;

struct SuperNode {
    int id;
    ll total_duration;
    ll total_urgency;

    // We want the HIGHEST urgency/duration ratio.
    // In a priority_queue, the "less" operator defines what goes to the BOTTOM.
    // So: a < b means "a is less urgent than b".
    bool operator<(const SuperNode& other) const {
        // Equivalent to: (urgency / duration) < (other.urgency / other.duration)
        return total_urgency * other.total_duration < other.total_urgency * total_duration;
    }
};

// DSU Structure to keep track of merged nodes and the execution sequence
struct DSU {
    vector<int> parent_map;
    vector<int> sequence_tail;
    vector<int> next_in_sequence;

    DSU(int n) {
        parent_map.resize(n);
        iota(parent_map.begin(), parent_map.end(), 0); // parent_map[i] = i
        sequence_tail.resize(n);
        iota(sequence_tail.begin(), sequence_tail.end(), 0);
        next_in_sequence.assign(n, -1);
    }

    int find(int i) {
        if (parent_map[i] == i) return i;
        return parent_map[i] = find(parent_map[i]);
    }

    // Connects the end of sequence 'u' to the start of sequence 'v'
    void merge_sequences(int u, int v) {
        int root_u = find(u);
        int root_v = find(v);
        
        // Link the physical sequence for the final walk
        next_in_sequence[sequence_tail[root_u]] = root_v;
        // Update the tail of the combined super-node
        sequence_tail[root_u] = sequence_tail[root_v];
        // DSU merge: v's root now points to u's root
        parent_map[root_v] = root_u;
    }
};

ll scheduling_cost(vector<int> p, vector<int> u, vector<int> d) {
    int n = p.size();
    DSU dsu(n);
    
    vector<ll> curr_u(u.begin(), u.end());
    vector<ll> curr_d(d.begin(), d.end());
    
    priority_queue<SuperNode> pq;

    // Initialize: Root (0) is special, others go in the PQ
    for (int i = 1; i < n; i++) {
        pq.push({i, curr_d[i], curr_u[i]});
    }

    // Tracking merged status to handle the "Lazy Deletion" in priority_queue
    vector<bool> is_merged(n, false);

    while (!pq.empty()) {
        SuperNode top = pq.top();
        pq.pop();

        int v = dsu.find(top.id);
        
        // Stale Check: If this node's stats don't match our current DSU stats, skip it
        if (is_merged[top.id] || curr_u[v] != top.total_urgency || curr_d[v] != top.total_duration) {
            continue;
        }

        // Find the parent of this super-node
        // p[v] is the original parent, we find its current super-node root
        int u_root = dsu.find(p[v]);

        // Merge v into u_root
        is_merged[v] = true; 
        dsu.merge_sequences(u_root, v);

        // Update the parent's stats
        curr_u[u_root] += top.total_urgency;
        curr_d[u_root] += top.total_duration;

        // If the new super-node isn't the root, put it back in the PQ
        if (u_root != 0) {
            pq.push({u_root, curr_d[u_root], curr_u[u_root]});
        }
    }

    // Calculate final cost by traversing the linked sequence starting at root (0)
    ll total_cost = 0;
    ll current_time = 0;
    int curr = 0;
    while (curr != -1) {
        current_time += d[curr];
        total_cost += current_time * u[curr];
        curr = dsu.next_in_sequence[curr];
    }

    return total_cost;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…