제출 #694651

#제출 시각아이디문제언어결과실행 시간메모리
694651sharaelong고대 책들 (IOI17_books)C++17
100 / 100
171 ms33960 KiB
#include "books.h" #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int, int> pii; const int MAX_N = 1e6 + 1; const ll INF = 4e18; int par[MAX_N]; int find(int x) { return par[x] = (x == par[x] ? x : find(par[x])); } bool visited[MAX_N]; int cycle_num[MAX_N]; int l[MAX_N], r[MAX_N]; int up[MAX_N]; int ldist[MAX_N], rdist[MAX_N], dist[MAX_N]; // minimum distance of moving cycle-component to its parent cycle-component int recent[MAX_N]; ll minimum_walk(vector<int> p, int s) { int n = p.size(); ll jump_len = 0; for (int i=0; i<n; ++i) jump_len += abs(i-p[i]); if (jump_len == 0) return 0; int cycle_cnt = 1; for (int i=0; i<n; ++i) { if (!cycle_num[i] && p[i] != i) { l[cycle_cnt] = i; for (int j=i; !cycle_num[j]; j=p[j]) { cycle_num[j] = cycle_cnt; r[cycle_cnt] = max(r[cycle_cnt], j); } cycle_cnt++; } } iota(par, par+n, 0); vector<int> st; for (int i=0; i<n; ++i) { if (cycle_num[i] > 0) { int c = find(cycle_num[i]); if (l[c] == i) { st.push_back(c); } else { while (!st.empty() && l[st.back()] > l[c]) { par[st.back()] = c; r[c] = max(r[c], r[st.back()]); st.pop_back(); } if (r[c] == i) { st.pop_back(); if (!st.empty()) up[c] = st.back(); } } } } for (int i=1; i<cycle_cnt; ++i) up[i] = find(up[i]); ll ans = 0; int last_root = 0; bool is_start_in_root = false; int root_min = n, root_max = -1; for (int i=1; i<cycle_cnt; ++i) { if (find(i) == i) { if (last_root > 0) { if (r[last_root] > l[i]) continue; ans += (l[i]-r[last_root]) * 2; } last_root = i; if (l[i] <= s && s <= r[i]) is_start_in_root = true; root_min = min(root_min, l[i]); root_max = max(root_max, r[i]); } } if (!is_start_in_root && root_min <= s && s <= root_max) return jump_len + ans; for (int i=0; i<n; ++i) { if (cycle_num[i] > 0) { int c = find(cycle_num[i]); recent[c] = i; if (up[c] > 0 && l[c] == i) ldist[c] = i-recent[up[c]]; if (r[c] == i) recent[up[c]] = max(recent[up[c]], i-ldist[c]); } } for (int i=n-1; i>=0; --i) { if (cycle_num[i] > 0) { int c = find(cycle_num[i]); recent[c] = i; if (up[c] > 0 && r[c] == i) rdist[c] = recent[up[c]]-i; if (l[c] == i) recent[up[c]] = min(recent[up[c]], rdist[c]+i); } } for (int i=1; i<cycle_cnt; ++i) dist[i] = min(ldist[i], rdist[i]); for (int i=1; i<cycle_cnt; ++i) { // cycle numbering is set by l[i] order // thus accumulation of dist in x-axis order is valid if (up[i] > 0) dist[i] += dist[up[i]]; } ll ans2 = INF; for (int i=0; i<n; ++i) { if (cycle_num[i] > 0) { int c = find(cycle_num[i]); ans2 = min(ans2, (ll)dist[c] + abs(i-s)); } } return jump_len + ans + ans2 * 2; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...