Submission #313455

#TimeUsernameProblemLanguageResultExecution timeMemory
313455VROOM_VARUNRailway Trip (JOI17_railway_trip)C++14
100 / 100
364 ms23684 KiB
/* ID: varunra2 LANG: C++ TASK: railways */ #include<bits/stdc++.h> using namespace std; #ifdef DEBUG #include "lib/debug.h" #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__) #define debug_arr(...) \ cerr << "[" << #__VA_ARGS__ << "]:", debug_arr(__VA_ARGS__) #pragma GCC diagnostic ignored "-Wsign-compare" //#pragma GCC diagnostic ignored "-Wunused-parameter" //#pragma GCC diagnostic ignored "-Wunused-variable" #else #define debug(...) 42 #endif #define EPS 1e-9 #define IN(A, B, C) assert(B <= A && A <= C) #define INF (int)1e9 #define MEM(a, b) memset(a, (b), sizeof(a)) #define MOD 1000000007 #define MP make_pair #define PB push_back #define all(cont) cont.begin(), cont.end() #define rall(cont) cont.end(), cont.begin() #define x first #define y second const double PI = acos(-1.0); typedef long long ll; typedef long double ld; typedef pair<int, int> PII; typedef map<int, int> MPII; typedef multiset<int> MSETI; typedef set<int> SETI; typedef set<string> SETS; typedef vector<int> VI; typedef vector<PII> VII; typedef vector<VI> VVI; typedef vector<string> VS; #define rep(i, a, b) for(int i = a; i < (b); ++i) #define trav(a, x) for(auto& a : x) #define sz(x) (int)(x).size() typedef pair<int, int> pii; typedef vector<int> vi; #pragma GCC diagnostic ignored "-Wsign-compare" // util functions const int siz = 20; int n, k, q; vector<VII> st; VI vals; VI prv; VI nxt; void init() { st.resize(n); vals.resize(n); prv.resize(n); nxt.resize(n); for(int i = 0; i < n; i++) { st[i].resize(siz); } } inline PII comb(PII a, int i) { // combining two ranges -> min of lefts/max of rights return MP(min(st[a.x][i].x, st[a.y][i].x), max(st[a.x][i].y, st[a.y][i].y)); } pair<int, PII> qry(int ind, int l, int r) { // what is the longest range originating form ind, that is within range l -> r? // also what is the minimum # of steps we need to take to reach it pair<int, PII> ret = MP(0, MP(ind, ind)); for(int i = siz - 1; i >= 0; i--) { PII cur = comb(ret.y, i); if(cur.x > l and cur.y < r) { ret.x += (1 << i); ret.y = cur; } } return ret; } int getDist(int a, int b) { if(a > b) swap(a, b); // answer will still stay the same, because graph is undirected auto ran1 = qry(a, -1, b); // without going into b's "territory", longest range auto ran2 = qry(b, ran1.y.y, n); // now in my territory return ran1.x + ran2.x + 1; // + 1 because you need to merge both ranges i think } void calcPrv() { // calculate previous greater or equal element index stack<int> s; for(int i = 0; i < n; i++) { while(!s.empty() and vals[s.top()] < vals[i]) s.pop(); if(s.empty()) prv[i] = -1; else prv[i] = s.top(); s.push(i); } prv[0] = 0; } void calcNxt() { // calculates next greater or equal element index stack<int> s; for(int i = n - 1; i >= 0; i--) { while(!s.empty() and vals[s.top()] < vals[i]) s.pop(); if(s.empty()) nxt[i] = n; else nxt[i] = s.top(); s.push(i); } nxt[n - 1] = n - 1; } int main() { // #ifndef ONLINE_JUDGE // freopen("railways.in", "r", stdin); // freopen("railways.out", "w", stdout); // #endif cin.sync_with_stdio(0); cin.tie(0); cin >> n >> k >> q; init(); for(int i = 0; i < n; i++) { cin >> vals[i]; } calcPrv(); calcNxt(); // for simple O(n ^ 2) solution, you can make an undirected unweighted graph out of prv/nxt, and answer is shortest path from a -> b for(int i = 0; i < n; i++) { st[i][0] = MP(prv[i], nxt[i]); } for(int j = 1; j < siz; j++) { for(int i = 0; i < n; i++) { st[i][j] = comb(st[i][j - 1], j - 1); } } while(q--) { int a, b; cin >> a >> b; a--, b--; cout << getDist(a, b) - 1 << '\n'; // minus one because ending node doesn't count } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...