#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
// A large enough value for infinity
const long long inf = 4e15 + 7; 
const int maxn = 3e5 + 5; 
struct segment {
    vector<long long> st;
    segment() {
        st.assign(4 * maxn + 5, inf);
    }
    void update(int id, int l, int r, int k, long long val) {
        if (l > r || k < l || k > r) return;
        if (l == r) {
            st[id] = min(st[id], val);
            return;
        }
        int mid = l + (r - l) / 2;
        if (k <= mid) {
            update(id * 2, l, mid, k, val);
        } else {
            update(id * 2 + 1, mid + 1, r, k, val);
        }
        st[id] = min(st[id * 2], st[id * 2 + 1]);
    }
    long long get(int id, int l, int r, int ul, int ur) {
        if (l > r || l > ur || r < ul) return inf;
        if (ul <= l && r <= ur) return st[id];
        
        int mid = l + (r - l) / 2;
        long long left_min = get(id * 2, l, mid, ul, ur);
        long long right_min = get(id * 2 + 1, mid + 1, r, ul, ur);
        return min(left_min, right_min);
    }
};
 
segment l, r; // l for column 1, r for column N
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    int M, N;
    cin >> M >> N;
    
    long long ans = inf;
    map<int, int> coordsToIdx;
    set<int> s;
    vector<tuple<int, int, int, int>> input(M);
    // Step 1: Coordinate Compression, including boundaries
    // This is the first critical fix confirmed by the editorial.
    s.insert(1);
    s.insert(N);
    
    for (int i = 0; i < M; i++) {
        cin >> get<0>(input[i]) >> get<1>(input[i]) >> get<2>(input[i]) >> get<3>(input[i]);
        s.insert(get<0>(input[i]));
        s.insert(get<1>(input[i]));
        s.insert(get<2>(input[i]));
    }
    int cnt = 0;
    for (int num : s) {
        coordsToIdx[num] = ++cnt;
    }
    
    int compressed_size = cnt;
    
    // Step 2: Initialize DP base cases
    // The cost to merge column 1 with itself is 0.
    // The cost to merge column N with itself is 0.
    l.update(1, 1, compressed_size, coordsToIdx[1], 0);
    r.update(1, 1, compressed_size, coordsToIdx[N], 0);
    
    // Step 3: Process devices and update DP states
    for (int i = 0; i < M; i++) {
        int ul = coordsToIdx[get<0>(input[i])];
        int ur = coordsToIdx[get<1>(input[i])];
        int k = coordsToIdx[get<2>(input[i])];
        int val = get<3>(input[i]);
        
        // Find the minimum cost to reach this device's *full range* [A_i, B_i]
        // This is the second critical fix.
        long long cost_from_left = l.get(1, 1, compressed_size, ul, ur);
        long long cost_from_right = r.get(1, 1, compressed_size, ul, ur);
        // Calculate a potential final answer if this device bridges the two paths
        if (cost_from_left < inf && cost_from_right < inf) {
             ans = min(ans, cost_from_left + cost_from_right + val);
        }
        // Update the DP states: this device creates a new, cheaper way to reach column C_i
        // Update the left-side (column 1) DP state
        if (cost_from_left < inf) {
             l.update(1, 1, compressed_size, k, cost_from_left + val);
        }
        // Update the right-side (column N) DP state
        if (cost_from_right < inf) {
             r.update(1, 1, compressed_size, k, cost_from_right + val);
        }
    }
    
    cout << (ans >= inf ? -1 : ans) << endl;
    return 0;
}
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |