QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#779463 | #365. Railway Trip | makrav | 0 | 1ms | 3968kb | C++20 | 7.2kb | 2024-11-24 19:15:21 | 2024-11-24 19:15:22 |
answer
#include <bits/stdc++.h>
#include <cassert>
using namespace std;
#define sz(x) (int)(x).size()
#define pb push_back
#define all(x) (x).begin(), (x).end()
template<typename T>
struct sparsetable {
int n;
vector<T> arr;
vector<vector<T>> sp;
function<T(T, T)> comp;
sparsetable() = default;
sparsetable(int n_, vector<T> arr_, function<T(T, T)> f) {
n = n_;
arr = arr_;
comp = f;
build();
}
void build() {
int lg = (int) log2(n) + 1;
sp.assign(lg, vector<T>(n));
for (int i = 0; i < n; i++) sp[0][i] = arr[i];
for (int i = 1; i <= lg; i++) {
for (int j = 0; j + (1 << i) - 1 < n; j++) {
sp[i][j] = comp(sp[i - 1][j], sp[i - 1][j + (1 << (i - 1))]);
}
}
}
T get(int l, int r) {
int lg = 31 - __builtin_clz(r - l + 1);
return comp(sp[lg][l], sp[lg][r - (1 << lg) + 1]);
}
};
const int LOGMAX = 17;
void solve() {
int n, k, q; cin >> n >> k >> q;
//cout << n << ' ' << k << ' ' << q << '\n';
vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
vector<pair<int, int>> b(n);
for (int i = 0; i < n; i++) b[i] = {a[i], i};
sparsetable<pair<int, int>> rmax(n, b, [](pair<int, int> p1, pair<int, int> p2){
if (p1.first != p2.first) return (p1.first < p2.first ? p2 : p1);
return (p1.second < p2.second ? p2 : p1);
}), rmin(n, b, [](pair<int, int> p1, pair<int, int> p2){
if (p1.first != p2.first) return (p1.first < p2.first ? p2 : p1);
return (p1.second < p2.second ? p1 : p2);
});
vector<vector<int>> g(n), g2(n);
vector<int> nxt(n, -1), prv(n, -1);
stack<int> st;
for (int i = n - 1; i >= 0; i--) {
while (!st.empty() && a[st.top()] < a[i]) st.pop();
if (!st.empty()) {
nxt[i] = st.top();
g2[i].pb(nxt[i]);
g2[nxt[i]].pb(i);
}
st.push(i);
}
while (!st.empty()) st.pop();
for (int i = 0; i < n; i++) {
while (!st.empty() && a[st.top()] < a[i]) st.pop();
if (!st.empty()) {
prv[i] = st.top();
g2[i].pb(prv[i]);
g2[prv[i]].pb(i);
}
st.push(i);
}
vector<int> rson(n, -1), lson(n, -1);
auto build = [&](int l, int r, int ps, auto&&self) -> void {
if (ps < r) {
int rp = rmin.get(ps + 1, r).second;
rson[ps] = rp;
g[ps].pb(rp);
g[rp].pb(ps);
self(ps + 1, r, rp, self);
}
if (ps > l) {
int lp = rmax.get(l, ps - 1).second;
lson[ps] = lp;
g[ps].pb(lp);
g[lp].pb(ps);
self(l, ps - 1, lp, self);
}
};
build(0, n - 1, 0, build);
vector<vector<pair<int, int>>> qrs(n);
vector<pair<int, int>> Q(q);
for (int i = 0; i < q; i++) {
int u, v; cin >> u >> v;
u--; v--;
Q[i] = {u, v};
qrs[u].pb({v, i});
qrs[v].pb({u, i});
}
vector<int> ans(q, n + 1);
//cout << ans.size() << '\n';
vector<int> tin(n), tout(n), h(n);
int timer = 0;
auto dfs = [&](int v, int p, auto&&self) -> void {
tin[v] = timer++;
for (int u : g[v]) {
if (u != p) {
h[u] = h[v] + 1;
self(u, v, self);
}
}
tout[v] = timer++;
};
dfs(0, 0, dfs);
auto is_par = [&](int v1, int v2) {
return tin[v1] <= tin[v2] && tout[v2] <= tout[v1];
};
vector<int> used_cent(n), need_find(n), siz(n), used(n);
vector<vector<int>> cent_cmp(n);
need_find[0] = 1;
int cur = 1, step = 0;
vector<int> curcmp;
auto dfs_siz = [&](int v, auto&&self) -> void {
siz[v] = 1; used[v] = step; curcmp.pb(v);
for (int u : g[v]) {
if (used[u] != step && !used_cent[u]) {
self(u, self);
siz[v] += siz[u];
}
}
};
auto find_cent = [&](int v, int init_size, auto&&self) -> int {
used[v] = step;
for (int u : g[v]) {
if (used[u] != step && !used_cent[u] && siz[u] > init_size / 2) return self(u, init_size, self);
}
return v;
};
while (true) {
bool allgood = true;
for (int i = 0; i < n; i++) {
if (need_find[i] == cur) {
curcmp.clear();
allgood = false;
step++; dfs_siz(i, dfs_siz); step++;
int vt = find_cent(i, siz[i], find_cent);
//cout << i << ' ' << cur << ' ' << vt << '\n';
used_cent[vt] = 1;
cent_cmp[vt] = curcmp;
for (int u : g[vt]) {
if (!used_cent[u]) need_find[u] = cur + 1;
}
}
}
if (allgood) break;
cur++;
}
vector<int> pos(n);
for (int i = 0; i < n; i++) {
// cout << i << endl;
// for (int u : cent_cmp[i]) cout << u << ' ';
// cout << endl;
step++;
for (int u : cent_cmp[i]) used[u] = step;
vector<int> curq;
for (int u : cent_cmp[i]) {
for (auto [v, num] : qrs[u]) {
if (v > u && used[v] == step) curq.pb(num);
}
}
unordered_set<int> roots;
roots.insert(i);
for (int u : cent_cmp[i]) {
if (u != i && nxt[u] != -1 && is_par(i, u) && is_par(nxt[u], i) && used[nxt[i]] == step) {
roots.insert(nxt[u]);
}
if (u != i && prv[u] != -1 && is_par(i, u) && is_par(prv[u], i) && used[prv[i]] == step) {
roots.insert(prv[u]);
}
}
for (int j = 0; j < cent_cmp[i].size(); j++) pos[cent_cmp[i][j]] = j;
vector<vector<int>> newg(sz(cent_cmp[i]));
for (int j = 0; j < cent_cmp[i].size(); j++) {
for (int u : g2[cent_cmp[i][j]]) {
if (used[u] == step) newg[j].pb(pos[u]);
}
}
for (int rt : roots) {
vector<int> dist(sz(cent_cmp[i]), -1);
//assert(rt == i || used[rt] == step);
dist[pos[rt]] = 0;
queue<int> q;
q.push(pos[rt]);
while (!q.empty()) {
int V = q.front();
q.pop();
for (int u : newg[V]) {
if (dist[u] == -1) {
dist[u] = dist[V] + 1;
q.push(u);
}
}
}
for (int qnum : curq) {
ans[qnum] = min(ans[qnum], dist[pos[Q[qnum].first]] + dist[pos[Q[qnum].second]]);
}
}
}
//cout << sz(ans) << '\n';
for (int el : ans) cout << el - 1 << '\n';
}
signed main() {
int tt = 1;
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
cin >> tt;
#else
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#endif
while (tt--) {
solve();
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Subtask #1:
score: 0
Runtime Error
Test #1:
score: 5
Accepted
time: 0ms
memory: 3660kb
input:
100 100 50 100 86 39 28 49 22 79 14 83 100 15 26 37 51 53 18 74 15 96 72 47 80 10 46 62 88 20 36 46 29 40 28 37 88 91 41 24 63 14 92 24 31 99 61 62 96 94 51 51 21 72 97 59 96 97 94 66 88 32 96 58 26 53 1 100 31 85 30 42 69 40 62 54 94 49 62 13 20 82 74 20 44 54 69 65 34 78 64 48 69 19 35 8 92 100 87...
output:
3 1 3 5 3 3 3 0 2 5 2 6 1 3 1 3 5 5 3 5 4 7 3 6 3 4 4 4 7 0 2 3 2 4 5 5 6 5 5 6 4 3 2 4 5 2 5 4 2 2
result:
ok 50 lines
Test #2:
score: 5
Accepted
time: 1ms
memory: 3712kb
input:
100 100 50 100 85 82 7 50 49 51 45 30 3 29 99 71 93 5 68 70 52 12 44 1 35 99 80 76 34 23 28 62 91 80 77 59 57 30 15 23 13 16 21 58 23 38 49 44 73 7 47 24 53 97 83 14 71 16 75 61 24 17 96 51 41 74 53 25 2 42 36 73 57 53 45 10 12 11 79 68 2 78 44 47 67 21 99 25 68 60 71 23 92 9 2 97 37 43 64 32 28 7 1...
output:
2 0 5 4 2 4 2 4 3 5 4 3 3 6 4 4 3 3 3 4 2 3 3 3 4 5 5 2 3 3 5 4 3 4 2 2 3 5 3 6 2 5 4 2 2 4 4 3 4 7
result:
ok 50 lines
Test #3:
score: 5
Accepted
time: 1ms
memory: 3832kb
input:
100 100 50 100 56 83 81 2 73 24 77 19 11 79 100 36 32 62 4 41 50 51 62 68 6 11 36 28 21 61 82 72 86 35 93 94 87 50 14 77 83 14 49 95 32 5 20 59 55 77 31 52 70 23 81 4 10 34 100 4 67 60 1 23 26 65 1 30 96 43 49 70 81 18 82 97 80 62 28 93 38 91 39 67 6 17 78 60 60 55 97 45 58 44 80 24 91 14 5 35 93 25...
output:
4 4 4 5 3 3 3 4 2 4 2 5 4 3 4 3 5 4 5 3 3 2 4 1 3 4 3 3 5 2 5 5 5 0 3 3 3 2 4 1 5 2 4 3 0 5 4 5 4 3
result:
ok 50 lines
Test #4:
score: 5
Accepted
time: 1ms
memory: 3968kb
input:
100 100 50 100 50 72 67 84 3 28 84 40 70 52 28 37 16 66 92 47 27 30 49 33 7 69 22 33 85 1 98 4 97 89 27 99 21 33 76 89 26 74 10 80 23 70 10 63 1 78 38 28 30 95 11 17 99 10 52 5 30 38 95 4 71 50 2 40 28 17 21 10 13 23 98 92 84 8 3 37 38 71 78 57 87 22 79 59 26 13 50 33 87 9 6 78 85 19 68 79 9 62 100 ...
output:
5 4 1 1 3 5 3 7 1 5 1 4 4 3 7 3 1 1 5 3 4 5 3 2 3 4 0 5 1 6 3 6 4 5 3 3 5 4 6 2 4 4 3 4 4 5 4 6 3 5
result:
ok 50 lines
Test #5:
score: 5
Accepted
time: 1ms
memory: 3716kb
input:
100 100 50 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 91 65 31 33 13 98 45 91 54 50 94 66 78 5 28 13 100 4 15 63 55 2 72 49 97 18 57 59 40 ...
output:
25 1 14 45 3 27 26 14 3 47 46 22 20 1 6 1 22 27 15 39 25 36 35 24 14 12 35 32 48 5 9 2 26 4 27 17 36 35 10 15 38 7 16 2 48 3 31 32 48 6
result:
ok 50 lines
Test #6:
score: 0
Runtime Error
input:
100 100 50 100 99 99 99 97 97 97 95 95 95 93 93 93 91 91 91 89 89 89 87 87 87 85 85 85 83 83 83 81 81 81 79 79 79 77 77 77 75 75 75 73 73 73 71 71 71 69 69 69 67 67 67 68 68 70 70 70 72 72 72 74 74 74 76 76 76 78 78 78 80 80 80 82 82 82 84 84 84 86 86 86 88 88 88 90 90 90 92 92 92 94 94 94 96 96 96 ...
output:
result:
Subtask #2:
score: 0
Skipped
Dependency #1:
0%
Subtask #3:
score: 0
Skipped
Dependency #1:
0%
Subtask #4:
score: 0
Skipped
Dependency #1:
0%