Submission #491315

#TimeUsernameProblemLanguageResultExecution timeMemory
491315blueTreatment Project (JOI20_treatment)C++17
35 / 100
400 ms41928 KiB
#include <iostream> #include <algorithm> #include <vector> #include <deque> #include <set> #include <queue> #include <cassert> using namespace std; using ll = long long; using pll = pair<ll, ll>; using vpll = vector<pll>; using vi = vector<int>; using vll = vector<ll>; using pii = pair<int, int>; struct project { int T; int L; int R; int C; int I; }; vector<project> P; const int maxM = 100'000; vi query_ans; vi visited(maxM, 0); const ll INF = 1'000'000'000'000'000'000LL; vll dp(maxM, INF); struct pos { int i; }; bool operator < (pos A, pos B) { if(dp[A.i] == dp[B.i]) return A.i < B.i; else return dp[A.i] < dp[B.i]; } struct segtree { // deque<int> v[220'000]; vector<int> v[1 << 18]; segtree() { ; } segtree(int L, int R) { ; } void add(int i, int l, int r, int I, ll Pr) { v[i].push_back(Pr); if(l != r) { if(I <= (l+r)/2) add(2*i, l, (l+r)/2, I, Pr); else add(2*i + 1, (l+r)/2+1, r, I, Pr); } } void getU(int i, int l, int r, int L, int R, ll mxv) { if(R < l || r < L || R < L) return; else if(L <= l && r <= R) { while(1) { if(v[i].empty()) break; if(P[v[i].back()].L + P[v[i].back()].T > mxv) break; if(!visited[v[i].back()]) { query_ans.push_back(v[i].back()); visited[v[i].back()] = 1; } v[i].pop_back(); } } else { getU(2*i, l, (l+r)/2, L, R, mxv); getU(2*i+1, (l+r)/2+1, r, L, R, mxv); } } void getD(int i, int l, int r, int L, int R, ll mxv) { if(R < l || r < L || R < L) return; else if(L <= l && r <= R) { while(1) { if(v[i].empty()) break; if(P[v[i].back()].L - P[v[i].back()].T > mxv) break; if(!visited[v[i].back()]) { query_ans.push_back(v[i].back()); visited[v[i].back()] = 1; } v[i].pop_back(); } } else { getD(2*i, l, (l+r)/2, L, R, mxv); getD(2*i+1, (l+r)/2+1, r, L, R, mxv); } } }; segtree U, D; int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); int N, M; cin >> N >> M; P = vector<project>(M); for(int i = 0; i < M; i++) cin >> P[i].T >> P[i].L >> P[i].R >> P[i].C; sort(P.begin(), P.end(), [] (project x, project y) { return x.T < y.T; }); for(int i = 0; i < M; i++) P[i].I = i; sort(P.begin(), P.end(), [] (project x, project y) { return x.L + x.T <= y.L + y.T; }); for(int i = 0; i < M; i++) U.add(1, 0, M-1, P[i].I, P[i].I); sort(P.begin(), P.end(), [] (project x, project y) { return x.L - x.T < y.L - y.T; }); for(int i = 0; i < M; i++) D.add(1, 0, M-1, P[i].I, P[i].I); for(int f = 0; f < (1 << 18); f++) { reverse(U.v[f].begin(), U.v[f].end()); reverse(D.v[f].begin(), D.v[f].end()); } sort(P.begin(), P.end(), [] (project x, project y) { return x.I < y.I; }); set<pos> tbv; for(int i = 0; i < M; i++) { if(P[i].L == 1) { dp[i] = P[i].C; visited[i] = 1; tbv.insert(pos{i}); } } while(!tbv.empty()) { int u = tbv.begin()->i; tbv.erase(tbv.begin()); // cerr << "visiting " << u << ' ' << P[u].L << ' ' << P[u].R << '\n'; query_ans.clear(); U.getU(1, 0, M-1, u+1, M-1, P[u].R + P[u].T + 1); D.getD(1, 0, M-1, 0, u-1, P[u].R - P[u].T + 1); for(int v: query_ans) { // cerr << u << " -> " << v << '\n'; assert(P[v].L <= P[u].R + 1 - abs(P[u].T - P[v].T)); assert(dp[v] == INF); dp[v] = dp[u] + P[v].C; tbv.insert(pos{v}); } } ll final_ans = INF; for(int i = 0; i < M; i++) if(P[i].R == N) final_ans = min(final_ans, dp[i]); if(final_ans >= INF) final_ans = -1; cout << final_ans << '\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...