This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <cstdio>
#include <algorithm>
#include <vector>
static const int MAXN = 100000;
static const int DEPTH = 20;
using namespace std;
struct segtree
{
static const int kDepth = 17;
static const int kSize = 1 << kDepth;
pair<int, int> *data;
segtree() {
data = new pair<int, int>[2 * kSize];
}
void init(int len, int* v)
{
for (int i = 0; i < len; ++i) data[kSize + i] = make_pair(v[i], -i);
for (int i = len; i < kSize; ++i) data[kSize + i] = make_pair(-1, -i);
for (int i = kSize - 1; i >= 1; --i) data[i] = max(data[i * 2], data[i * 2 + 1]);
}
pair<int, int> query(int l, int r)
{
l += kSize;
r += kSize;
pair<int, int> ret(-1, -1);
while (l < r) {
if (l & 1) ret = max(ret, data[l++]);
if (r & 1) ret = max(ret, data[--r]);
l >>= 1; r >>= 1;
}
ret.second = -ret.second;
return ret;
}
};
int N, K, Q;
int L[MAXN];
vector<int> child[MAXN * 2]; int dep[MAXN * 2], ci[MAXN * 2];
int nlast, root;
int wnode[MAXN];
segtree lst;
bool nonstop;
int parent[MAXN * 6][DEPTH], weight[MAXN * 6][DEPTH];
int build(int l, int r)
{
if (r - l == 1) {
return wnode[l] = nlast++;
}
auto tmp = lst.query(l + 1, r);
int bp = tmp.first;
vector<int> sep;
sep.push_back(l);
sep.push_back(tmp.second);
for (;;) {
auto q = lst.query(sep.back() + 1, r);
if (q.first != bp) break;
sep.push_back(q.second);
}
sep.push_back(r);
int ret = nlast++;
for (int i = 0; i < (int)sep.size() - 1; ++i) {
child[ret].push_back(build(sep[i], sep[i + 1]));
}
return ret;
}
inline int forest_vtx(int p, int mode)
{
// mode 0: (x+1, x), 1: (x, x), 2: (x, x+1)
return p * 3 + mode;
}
void assign_parent(int p, int par, int tl, int tr)
{
tl = min(tl, tr + 1);
tr = min(tr, tl + 1);
if (tl == tr + 1) {
parent[p][0] = forest_vtx(par, 0);
weight[p][0] = tr;
} else if (tl == tr) {
parent[p][0] = forest_vtx(par, 1);
weight[p][0] = tr;
} else {
parent[p][0] = forest_vtx(par, 2);
weight[p][0] = tl;
}
}
void gen_forest(int p)
{
for (int p2 = p * 3; p2 < (p + 1) * 3; ++p2) {
for (int i = 1; i < DEPTH; ++i) {
if (parent[p2][i - 1] == -1) {
parent[p2][i] = -1;
weight[p2][i] = weight[p2][i - 1];
} else {
parent[p2][i] = parent[parent[p2][i - 1]][i - 1];
weight[p2][i] = weight[p2][i - 1] + weight[parent[p2][i - 1]][i - 1];
}
}
}
for (int i = 0; i < child[p].size(); ++i) {
int q = child[p][i];
int j = (int)child[p].size() - i - 1;
dep[q] = dep[p] + 1;
ci[q] = i;
assign_parent(forest_vtx(q, 0), p, 1 + i, j);
assign_parent(forest_vtx(q, 1), p, i, j);
assign_parent(forest_vtx(q, 2), p, i, j + 1);
gen_forest(q);
}
}
pair<int, int> descend(int p, int d)
{
int dist = 0;
for (int i = DEPTH - 1; i >= 0; --i) if (d & (1 << i)) {
dist += weight[p][i];
p = parent[p][i];
}
return{ p, dist };
}
int solve(int a, int b)
{
if (b == a + 1) return 1;
int p = forest_vtx(wnode[a], 2);
int q = forest_vtx(wnode[b - 1], 0);
int dist = 0;
if (dep[p / 3] < dep[q / 3]) {
auto tmp = descend(q, dep[q / 3] - dep[p / 3]);
dist = tmp.second;
q = tmp.first;
} else if (dep[p / 3] > dep[q / 3]) {
auto tmp = descend(p, dep[p / 3] - dep[q / 3]);
dist = tmp.second;
p = tmp.first;
}
for (int i = DEPTH - 1; i >= 0; --i) {
if (parent[p][i] / 3 != parent[q][i] / 3) {
dist += weight[p][i] + weight[q][i];
p = parent[p][i];
q = parent[q][i];
}
}
int ret = N;
ret = min(ret, dist + ci[q / 3] - ci[p / 3] - 1 + (p % 3 == 2 ? 1 : 0) + (q % 3 == 0 ? 1 : 0));
if (parent[p][0] / 3 != root || nonstop) {
ret = min(ret, dist + ci[p / 3] + ((int)child[parent[p][0] / 3].size() - ci[q / 3] - 1) + (p % 3 == 0 ? 1 : 0) + (q % 3 == 2 ? 1 : 0) + 1);
}
return ret;
}
int main()
{
scanf("%d%d%d", &N, &K, &Q);
nonstop = true;
for (int i = 0; i < N; ++i) {
scanf("%d", L + i);
--L[i];
if (i != 0 && i != N - 1 && L[i] == K - 1) nonstop = false;
}
nlast = 0;
lst.init(N, L);
root = build(0, N - 1);
dep[root] = 0; ci[root] = 0;
for (int i = 0; i < 3; ++i) {
parent[root * 3 + i][0] = -1;
weight[root * 3 + i][0] = 0;
}
gen_forest(root);
for (int q = 0; q < Q; ++q) {
int a, b;
scanf("%d%d", &a, &b);
--a; --b;
if (a > b) swap(a, b);
printf("%d\n", solve(a, b) - 1);
}
return 0;
}
Compilation message (stderr)
railway_trip.cpp: In function 'int main()':
railway_trip.cpp:157:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%d%d%d", &N, &K, &Q);
~~~~~^~~~~~~~~~~~~~~~~~~~~~
railway_trip.cpp:160:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%d", L + i);
~~~~~^~~~~~~~~~~~~
railway_trip.cpp:177:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%d%d", &a, &b);
~~~~~^~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |