結果
| 問題 |
No.2242 Cities and Teleporters
|
| コンテスト | |
| ユーザー |
hitonanode
|
| 提出日時 | 2023-03-11 00:05:34 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 392 ms / 3,000 ms |
| コード長 | 3,048 bytes |
| コンパイル時間 | 1,427 ms |
| コンパイル使用メモリ | 110,736 KB |
| 実行使用メモリ | 39,200 KB |
| 最終ジャッジ日時 | 2024-09-18 05:48:39 |
| 合計ジャッジ時間 | 10,187 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 26 |
ソースコード
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define ALL(x) (x).begin(), (x).end()
#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define REP(i, n) FOR(i,0,n)
template <typename T> bool chmax(T &m, const T q) { return m < q ? (m = q, true) : false; }
template <class T> std::vector<T> sort_unique(std::vector<T> vec) { sort(vec.begin(), vec.end()), vec.erase(unique(vec.begin(), vec.end()), vec.end()); return vec; }
template <class T> int arglb(const std::vector<T> &v, const T &x) { return std::distance(v.begin(), std::lower_bound(v.begin(), v.end(), x)); }
template <class IStream, class T> IStream &operator>>(IStream &is, std::vector<T> &vec) { for (auto &v : vec) is >> v; return is; }
// Binary lifting / `Doubling`
// Complexity: O(NlogN) precalculation / O(logN) per query
// <https://atcoder.jp/contests/arc060/submissions/7039451>
struct BinaryLifting {
int N, INVALID, lgD;
std::vector<std::vector<int>> mat;
BinaryLifting() : N(0), lgD(0) {}
BinaryLifting(const std::vector<int> &vec_nxt, int INVALID = -1, int lgd = 0)
: N(vec_nxt.size()), INVALID(INVALID), lgD(lgd) {
while ((1LL << lgD) < N) lgD++;
mat.assign(lgD, std::vector<int>(N, INVALID));
mat[0] = vec_nxt;
for (int i = 0; i < N; i++)
if (mat[0][i] < 0 or mat[0][i] >= N) mat[0][i] = INVALID;
for (int d = 0; d < lgD - 1; d++) {
for (int i = 0; i < N; i++)
if (mat[d][i] != INVALID) mat[d + 1][i] = mat[d][mat[d][i]];
}
}
int kth_next(int now, long long k) {
if (k >= (1LL << lgD)) exit(8);
for (int d = 0; k and now != INVALID; d++, k >>= 1)
if (k & 1) now = mat[d][now];
return now;
}
// Distance from l to [r, \infty)
// Requirement: mat[0][i] > i for all i (monotone increasing)
int distance(int l, int r) {
if (l >= r) return 0;
int ret = 0;
for (int d = lgD - 1; d >= 0; d--) {
if (mat[d][l] < r and mat[d][l] != INVALID) ret += 1 << d, l = mat[d][l];
}
if (mat[0][l] == INVALID or mat[0][l] >= r)
return ret + 1;
else
return -1; // Unable to reach
}
};
int main() {
cin.tie(nullptr), ios::sync_with_stdio(false);
int N;
cin >> N;
vector<int> H(N), T(N);
cin >> H >> T;
auto z = H;
z.insert(z.end(), ALL(T));
z = sort_unique(z);
for (auto &x : H) x = arglb(z, x);
for (auto &x : T) x = arglb(z, x);
const int sz = z.size();
vector<int> to(sz);
REP(i, sz) to.at(i) = i;
REP(i, N) chmax(to.at(H.at(i)), T.at(i));
FOR(i, 1, sz) chmax(to.at(i), to.at(i - 1));
BinaryLifting bl(to);
int Q;
cin >> Q;
while (Q--) {
int a, b;
cin >> a >> b;
--a, --b;
int h1 = T.at(a);
int hgoal = H.at(b);
auto ret = bl.distance(h1, hgoal);
if (ret >= 0) {
++ret;
}
cout << ret << '\n';
}
}
hitonanode