Submission #1020439

#TimeUsernameProblemLanguageResultExecution timeMemory
1020439underwaterkillerwhaleTreatment Project (JOI20_treatment)C++17
100 / 100
366 ms59420 KiB
#include <bits/stdc++.h>
#define se              second
#define fs              first
#define mp              make_pair
#define pb              push_back
#define ll              long long
#define ii              pair<ll,ll>
#define ld              long double
#define SZ(v)           (int)v.size()
#define ALL(v)          v.begin(), v.end()
#define bit(msk, i)     ((msk >> i) & 1)
#define iter(id, v)     for(auto id : v)
#define rep(i,m,n)      for(int i=(m); i<=(n); i++)
#define reb(i,m,n)      for(int i=(m); i>=(n); i--)

using namespace std;

mt19937_64 rd(chrono :: steady_clock :: now().time_since_epoch().count());
ll Rand(ll l, ll r)
{
    return uniform_int_distribution<ll> (l, r)(rd);
}

const int N  = 2e5 + 7;
const int Mod =1e9 + 7;
const int szBL = 916;
const int INF = 2e9 + 7;
const int BASE = 137;


struct Data {
    ll T, L, R, C;
};

int n, m;
Data a[N];
vector<pair<ll,ll>> ke[N];
ll Dist[N];
vector<ll> Val; int nVal;

struct Segment_Tree_Set {
    int Range;
    set<pair<int, int>> sval[N];
    pair<int,int> st[N << 2];

    void init (int n ) {
        Range = n;
    }
    void Merge (int id) {
        if (st[id << 1].fs <= st[id << 1 | 1].fs) st[id] = st[id << 1];
        else st[id] = st[id << 1 | 1];
    }
    void update (int id, int l, int r, int pos, pair<int, int> cur) {
        if (l > pos || r < pos) return;
        if (l == r) {
            sval[l].insert(cur);
            st[id] = *sval[l].begin();
            return;
        }
        int mid = l + r >> 1;
        update (id << 1, l, mid, pos, cur);
        update (id << 1 | 1, mid + 1, r, pos, cur);
        Merge (id);
    }
    void deupdate (int id, int l, int r, int pos, pair<int,int> cur){
        if (l > pos || r < pos) return;
        if (l == r) {
            sval[l].erase(sval[l].find(cur));
            if (sval[l].empty()) st[id] = {INF, -1};
            else st[id] = *sval[l].begin();
            return;
        }
        int mid = l + r >> 1;
        deupdate (id << 1, l, mid, pos, cur);
        deupdate (id << 1 | 1, mid + 1, r, pos, cur);
        Merge (id);
    }
    pair<int,int> get (int id, int l, int r, int u, int v) {
        if (l > v || r < u) return {INF, -1};
        if (l >= u && r <= v) return st[id];
        int mid = l + r >> 1;
        pair<int,int> p1 = get (id << 1, l, mid, u, v),
                        p2 = get (id << 1 | 1, mid + 1, r, u, v);
        if (p1.fs <= p2.fs) return p1;
        else return p2;
    }

    void update (int pos, pair<int,int> cur) {
        update (1, 1, Range, pos, cur);
    }
    void deupdate (int pos, pair<int,int> cur) {
        deupdate (1, 1, Range, pos, cur);
    }
    pair<int,int> get (int u, int v) {
        return get (1, 1, Range, u, v);
    }

}ST1, ST2;

void solution () {
    cin >> n >> m;
    rep (i, 1, m) {
        cin >> a[i].T >> a[i].L >> a[i].R >> a[i].C;
        --a[i].L;
    }
    rep (i, 1, m) {
        Val.push_back(a[i].T);
    }
    sort (ALL(Val));
    Val.resize(nVal = unique(ALL(Val)) - Val.begin());
    ST1.init(nVal);
    ST2.init(nVal);
    /**
        1: a[i].R + a[i].T >= a[j].R + a[j].T ti < tj
        2: a[i].R - a[i].T >= a[j].L - a[j].T ti > tj
    */
    auto CPR = [] (int val) {
        return lower_bound(ALL(Val), val) - Val.begin() + 1;
    };
    rep (i, 1, m) {
        int pos = CPR(a[i].T);
        ST1.update (pos, mp(a[i].L + a[i].T, i));
        ST2.update (pos, mp(a[i].L - a[i].T, i));
    }
    memset(Dist, 0x3f, sizeof Dist);
    priority_queue<pair<ll,ll>, vector<pair<ll,ll>>, greater<pair<ll,ll>>> pq;
    rep (i, 1, m) {
        if (a[i].L == 0) {
            pq.push({a[i].C, i});
            Dist[i] = a[i].C;
        }
    }
    while (!pq.empty()) {
        int u = pq.top().se;
        if (a[u].R == n) {
            cout << Dist[u] <<"\n";
            return;
        }
        pq.pop();
        int pos = CPR(a[u].T);
        while (1) {
            int v = ST1.get(pos, nVal).se;
//            cout << u <<" "<<v<<" a \n";
            if (v == -1 || a[u].R + a[u].T < a[v].L + a[v].T) break;
            Dist[v] = min(Dist[v], Dist[u] + a[v].C);
            pq.push({Dist[v], v});
            ST1.deupdate (CPR(a[v].T), mp(a[v].L + a[v].T, v));
        }
        while (1) {
            int v = ST2.get(1, pos).se;
//            cout << u <<" "<<v<<" b\n";
            if (v == -1 || a[u].R - a[u].T < a[v].L - a[v].T) break;
            Dist[v] = min(Dist[v], Dist[u] + a[v].C);
            pq.push({Dist[v], v});
            ST2.deupdate (CPR(a[v].T), mp(a[v].L - a[v].T, v));
        }
    }
    cout << -1 <<"\n";
}

#define file(name) freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout);
int main () {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
//    file ("c");
    int num_Test = 1;
//    cin >> num_Test;
    while (num_Test--)
        solution();
}
/*
1 2
*/

Compilation message (stderr)

treatment.cpp: In member function 'void Segment_Tree_Set::update(int, int, int, int, std::pair<int, int>)':
treatment.cpp:60:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   60 |         int mid = l + r >> 1;
      |                   ~~^~~
treatment.cpp: In member function 'void Segment_Tree_Set::deupdate(int, int, int, int, std::pair<int, int>)':
treatment.cpp:73:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   73 |         int mid = l + r >> 1;
      |                   ~~^~~
treatment.cpp: In member function 'std::pair<int, int> Segment_Tree_Set::get(int, int, int, int, int)':
treatment.cpp:81:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   81 |         int mid = l + r >> 1;
      |                   ~~^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...