QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#877773#2559. Endless RoadbobbilykingWA 0ms3712kbC++174.2kb2025-02-01 05:24:582025-02-01 05:24:59

Judging History

This is the latest submission verdict.

  • [2025-02-01 05:24:59]
  • Judged
  • Verdict: WA
  • Time: 0ms
  • Memory: 3712kb
  • [2025-02-01 05:24:58]
  • Submitted

answer

#include <bits/stdc++.h>
using namespace std;
 
// Structure for a member’s interval
struct Interval {
    int id; // member number (1-indexed)
    int L, R; // interval [L,R)
};
 
// For the priority queue we will store a candidate with its currently recorded cost and its index in the intervals vector.
struct Node {
    long long cost; // current "new planting" cost
    int id;        // index in intervals vector (0-indexed)
    // Break ties by member id (which corresponds to the given index)
    bool operator>(const Node &other) const {
        if(cost == other.cost) return id > other.id;
        return cost > other.cost;
    }
};
 
// --- Data structure for maintaining the union U ---
// We maintain U as a set of disjoint intervals (each represented as a pair {l, r}) and sorted by l.
 
// Given the current union U, compute the total length of overlap with [L, R).
long long computeOverlap(const set<pair<int,int>> &U, int L, int R) {
    long long overlap = 0;
    // Get the first interval in U that might intersect [L,R).
    auto it = U.upper_bound({L, INT_MAX});
    if(it != U.begin()){
        it--;
    }
    // Iterate over intervals in U that might intersect.
    for(; it != U.end(); it++){
        int il = it->first, ir = it->second;
        if(ir <= L) continue;
        if(il >= R) break;
        int interL = max(L, il);
        int interR = min(R, ir);
        if(interR > interL)
            overlap += (long long)(interR - interL);
    }
    return overlap;
}
 
// Merge the segment [a, b) into the union U.
void addUnion(set<pair<int,int>> &U, int a, int b) {
    if(a >= b) return;
    auto it = U.lower_bound({a, -1});
    if(it != U.begin()){
        auto prev = it;
        prev--;
        if(prev->second >= a) { // they overlap
            a = min(a, prev->first);
            b = max(b, prev->second);
            it = U.erase(prev);
        }
    }
    while(it != U.end() && it->first <= b){
        b = max(b, it->second);
        it = U.erase(it);
    }
    U.insert({a, b});
}
 
// Main function
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    int N; 
    cin >> N;
    vector<Interval> intervals(N);
    for (int i = 0; i < N; i++){
        int L, R;
        cin >> L >> R;
        intervals[i] = {i+1, L, R}; // member numbers are 1-indexed.
    }
    // According to the problem statement the intervals are given so that (R_i-L_i) is nondecreasing with i.
 
    // Priority queue for candidates. (We use a min–heap by cost; if costs tie, the lower id wins.)
    priority_queue<Node, vector<Node>, greater<Node>> pq;
    // Initially, each member’s cost is its full length.
    for (int i = 0; i < N; i++){
        int len = intervals[i].R - intervals[i].L;
        pq.push({(long long)len, i});
    }
 
    vector<bool> selected(N, false);
    vector<int> order; 
    order.reserve(N);
 
    // U will hold the union of all positions that have already been planted.
    set<pair<int,int>> U;  // intervals as (l, r)
 
    // Simulation loop: in each turn we choose one member.
    while(!pq.empty()){
        Node cur = pq.top();
        pq.pop();
        int idx = cur.id;
        if(selected[idx]) continue; // Already chosen.
 
        // Recompute the candidate’s cost from the current union.
        int L = intervals[idx].L, R = intervals[idx].R;
        long long tot = (long long) R - L;
        long long cov = computeOverlap(U, L, R);
        long long curCost = tot - cov;
        if(curCost != cur.cost){
            // Our stored cost is stale – push an update.
            pq.push({curCost, idx});
            continue;
        }
 
        // This candidate is chosen.
        selected[idx] = true;
        order.push_back(intervals[idx].id);
 
        // The member “plants” on the parts of its interval not already covered.
        // (We do not need to compute the difference exactly – it is enough to update U to U ∪ [L,R).)
        addUnion(U, L, R);
    }
 
    // Output the final planting order.
    // (The i–th output number is the index of the member chosen in turn i.)
    for (int i = 0; i < order.size(); i++){
        cout << order[i] << (i+1 == order.size() ? "\n" : " ");
    }
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 0ms
memory: 3712kb

input:

6
1 2
2 3
3 4
4 5
1 3
3 5

output:

1 2 3 4 5 6

result:

wrong answer 3rd words differ - expected: '5', found: '3'