This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <cassert>
#include <ctime>
#include <chrono>
#include <cstdio>
#include <random>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <deque>
#include <queue>
#include <bitset>
#include <list>
#include <fstream>
#include <functional>
#include <complex>
#include "jumps.h"
using namespace std;
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int INF = 1e9, MOD = 1e9 + 7, MOD2 = 998244353, LOG = 20;
const long double EPS = 1e-9, PI = acos(-1);
struct sparse_table
{
int n;
vector<int> h, lg2;
vector<vector<int>> t;
sparse_table() {}
sparse_table(vector<int>& in)
{
n = in.size();
h = in;
lg2.resize(n + 1);
for (int i = 2; i < n + 1; i++)
{
lg2[i] = lg2[i / 2] + 1;
}
t.resize(lg2[n] + 1);
t[0].resize(n);
iota(t[0].begin(), t[0].end(), 0);
for (int i = 1; i < t.size(); i++)
{
int len = (1ll << i);
t[i].resize(n - len + 1);
for (int j = 0; j < t[i].size(); j++)
{
if (h[t[i - 1][j]] > h[t[i - 1][j + len / 2]])
{
t[i][j] = t[i - 1][j];
}
else
{
t[i][j] = t[i - 1][j + len / 2];
}
}
}
}
int get(int l, int r)
{
int lg = lg2[r - l + 1];
if (h[t[lg][l]] > h[t[lg][r - (1ll << lg) + 1]])
{
return t[lg][l];
}
else
{
return t[lg][r - (1ll << lg) + 1];
}
}
};
sparse_table sptb;
vector<int> v, gtl, gtr;
vector<vector<int>> bingt, binls;
void init(int n, std::vector<int> h)
{
v = h;
sptb = sparse_table(h);
gtl.resize(n, -1);
vector<int> st;
for (int i = 0; i < n; i++)
{
while (st.size() && v[st.back()] <= v[i])
{
st.pop_back();
}
if (st.size())
{
gtl[i] = st.back();
}
st.push_back(i);
}
gtr.resize(n, n);
st = {};
for (int i = n - 1; i > -1; i--)
{
while (st.size() && v[st.back()] <= v[i])
{
st.pop_back();
}
if (st.size())
{
gtr[i] = st.back();
}
st.push_back(i);
}
bingt.resize(n, vector<int>(LOG, -1));
binls.resize(n, vector<int>(LOG, -1));
for (int i = 0; i < n; i++)
{
if (gtl[i] == -1 && gtr[i] == n)
{
continue;
}
if (gtl[i] == -1)
{
bingt[i][0] = binls[i][0] = gtr[i];
}
if (gtr[i] == n)
{
bingt[i][0] = binls[i][0] = gtl[i];
}
if (gtl[i] != -1 && gtr[i] != n)
{
if (v[gtl[i]] > v[gtr[i]])
{
bingt[i][0] = gtl[i];
binls[i][0] = gtr[i];
}
else
{
bingt[i][0] = gtr[i];
binls[i][0] = gtl[i];
}
}
}
for (int i = 1; i < LOG; i++)
{
for (int j = 0; j < n; j++)
{
if (binls[j][i - 1] != -1)
{
binls[j][i] = binls[binls[j][i - 1]][i - 1];
}
if (bingt[j][i - 1] != -1)
{
bingt[j][i] = bingt[bingt[j][i - 1]][i - 1];
}
}
}
}
int minimum_jumps(int a, int b, int c, int d)
{
int mxto = sptb.get(c, d);
int bsl = a - 1, bsr = b + 1;
while (bsr - bsl > 1)
{
int mid = (bsl + bsr) / 2;
if (v[sptb.get(mid, b)] < v[mxto])
{
bsr = mid;
}
else
{
bsl = mid;
}
}
if (bsr == b + 1)
{
return -1;
}
a = bsr;
if (b < c - 1)
{
if (v[sptb.get(b + 1, c - 1)] > v[mxto])
{
return -1;
}
}
d = mxto;
if (b == c - 1)
{
return 1;
}
int fr = sptb.get(a, b);
int btw = sptb.get(b + 1, c - 1);
if (v[fr] > v[btw])
{
return 1;
}
int ans = 0;
for (int i = LOG - 1; i > -1; i--)
{
if (bingt[fr][i] == -1 || v[bingt[fr][i]] >= v[btw])
{
continue;
}
ans += (1ll << i);
fr = bingt[fr][i];
}
if (bingt[fr][0] != -1 && v[bingt[fr][0]] < v[mxto])
{
return ans + 2;
}
for (int i = LOG - 1; i > -1; i--)
{
if (binls[fr][i] == -1 || v[binls[fr][i]] > v[btw])
{
continue;
}
ans += (1ll << i);
fr = binls[fr][i];
}
return ans + 1;
}
/*
int fuck(int a, int b, int c, int d)
{
int n = v.size();
vector<int> dist(n, INF);
deque<int> q;
for (int i = a; i < b + 1; i++)
{
dist[i] = 0;
q.push_back(i);
}
while (q.size())
{
long long ver = q.front();
q.pop_front();
if (gtl[ver] != -1)
{
if (dist[gtl[ver]] > dist[ver] + 1)
{
dist[gtl[ver]] = dist[ver] + 1;
q.push_back(gtl[ver]);
}
}
if (gtr[ver] != n)
{
if (dist[gtr[ver]] > dist[ver] + 1)
{
dist[gtr[ver]] = dist[ver] + 1;
q.push_back(gtr[ver]);
}
}
}
int ans = INF;
for (int i = c; i < d + 1; i++)
{
ans = min(ans, dist[i]);
}
if (ans == INF)
{
return -1;
}
return ans;
}
int main()
{
while (true)
{
int N = 100;
std::vector<int> H(N);
iota(H.begin(), H.end(), 1);
shuffle(H.begin(), H.end(), rnd);
init(N, H);
vector<int> prr(N);
iota(prr.begin(), prr.end(), 0);
shuffle(prr.begin(), prr.end(), rnd);
vector<int> idk = { prr[0], prr[1], prr[2], prr[3] };
sort(idk.begin(), idk.end());
if (minimum_jumps(idk[0], idk[1], idk[2], idk[3]) != fuck(idk[0], idk[1], idk[2], idk[3]))
{
cout << "PSODVNOSNDV\n";
return 0;
}
cout << "OK\n";
sptb = {};
v = gtl = gtr = {};
bingt = binls = {};
}
return 0;
int N = 0, Q = 0;
assert(2 == scanf("%d %d", &N, &Q));
std::vector<int> H(N);
for (int i = 0; i < N; ++i)
{
assert(1 == scanf("%d", &H[i]));
}
init(N, H);
for (int i = 0; i < Q; ++i)
{
int A = 0, B = 0, C = 0, D = 0;
assert(4 == scanf("%d %d %d %d", &A, &B, &C, &D));
printf("%d\n", minimum_jumps(A, B, C, D));
}
return 0;
}
*/
/*
<3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠤⠖⠚⢉⣩⣭⡭⠛⠓⠲⠦⣄⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢀⡴⠋⠁⠀⠀⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠳⢦⡀⠀⠀⠀⠀
⠀⠀⠀⠀⢀⡴⠃⢀⡴⢳⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣆⠀⠀⠀
⠀⠀⠀⠀⡾⠁⣠⠋⠀⠈⢧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢧⠀⠀
⠀⠀⠀⣸⠁⢰⠃⠀⠀⠀⠈⢣⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣇⠀
⠀⠀⠀⡇⠀⡾⡀⠀⠀⠀⠀⣀⣹⣆⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⠀
⠀⠀⢸⠃⢀⣇⡈⠀⠀⠀⠀⠀⠀⢀⡑⢄⡀⢀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇
⠀⠀⢸⠀⢻⡟⡻⢶⡆⠀⠀⠀⠀⡼⠟⡳⢿⣦⡑⢄⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇
⠀⠀⣸⠀⢸⠃⡇⢀⠇⠀⠀⠀⠀⠀⡼⠀⠀⠈⣿⡗⠂⠀⠀⠀⠀⠀⠀⠀⢸⠁
⠀⠀⡏⠀⣼⠀⢳⠊⠀⠀⠀⠀⠀⠀⠱⣀⣀⠔⣸⠁⠀⠀⠀⠀⠀⠀⠀⢠⡟⠀
⠀⠀⡇⢀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀
⠀⢸⠃⠘⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠁⠀⠀⢀⠀⠀⠀⠀⠀⣾⠀⠀
⠀⣸⠀⠀⠹⡄⠀⠀⠈⠁⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠸⠀⠀⠀⠀⠀⡇⠀⠀
⠀⡏⠀⠀⠀⠙⣆⠀⠀⠀⠀⠀⠀⠀⢀⣠⢶⡇⠀⠀⢰⡀⠀⠀⠀⠀⠀⡇⠀⠀
⢰⠇⡄⠀⠀⠀⡿⢣⣀⣀⣀⡤⠴⡞⠉⠀⢸⠀⠀⠀⣿⡇⠀⠀⠀⠀⠀⣧⠀⠀
⣸⠀⡇⠀⠀⠀⠀⠀⠀⠉⠀⠀⠀⢹⠀⠀⢸⠀⠀⢀⣿⠇⠀⠀⠀⠁⠀⢸⠀⠀
⣿⠀⡇⠀⠀⠀⠀⠀⢀⡤⠤⠶⠶⠾⠤⠄⢸⠀⡀⠸⣿⣀⠀⠀⠀⠀⠀⠈⣇⠀
⡇⠀⡇⠀⠀⡀⠀⡴⠋⠀⠀⠀⠀⠀⠀⠀⠸⡌⣵⡀⢳⡇⠀⠀⠀⠀⠀⠀⢹⡀
⡇⠀⠇⠀⠀⡇⡸⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠮⢧⣀⣻⢂⠀⠀⠀⠀⠀⠀⢧
⣇⠀⢠⠀⠀⢳⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡎⣆⠀⠀⠀⠀⠀⠘
⢻⠀⠈⠰⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⠘⢮⣧⡀⠀⠀⠀⠀
⠸⡆⠀⠀⠇⣾⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠆⠀⠀⠀⠀⠀⠀⠀⠙⠳⣄⡀⢢⡀
<3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3
*/
Compilation message (stderr)
jumps.cpp: In constructor 'sparse_table::sparse_table(std::vector<int>&)':
jumps.cpp:53:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
53 | for (int i = 1; i < t.size(); i++)
| ~~^~~~~~~~~~
jumps.cpp:57:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
57 | for (int j = 0; j < t[i].size(); j++)
| ~~^~~~~~~~~~~~~
# | 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... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |