原题链接
- 题意:给出 \(n<=1e5\) 个旅店的位置,然后人一天最远走 \(L<=1e9\) 长度的路,必须在旅店住一晚上,然后有 \(m <= 1e5\) 个询问,要求出从 \(a\) 旅店到 \(b\) 旅店最少要多少天才能到。
- 题解:只想到了从 \(n\) 和 \(n-1\) 双指针得出 \(i\) 一天最远走到哪个旅店,然后就卡了,还想二分啥的,结果瞄一眼题解倍增,然后自己就恍然大悟。就是第一步算出来了,就相当于是 \(f_{i,0}\) 求出来了,\(f_{i, j}\) 代表的是从 \(i\) 点走 \(2^j\) 天最远到的旅店位置,然后就是类似lca的做法了。
- 代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
#include <cstring>
#include <map>
using namespace std;
const int N = 2e5 + 99;
typedef long long ll;
const ll mod = 1000000007;
const int inf = 0x3f3f3f3f;
int a[N];
int f[N][33];
void solve() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int k;cin >> k;
memset(f, 0x3f, sizeof f);
for (int j = n, i = n-1; j >= 1; j--) {
while (a[j] - a[i] <= k && i >= 1) {
f[i][0] = j;
i--;
}
}
for (int i = n - 1; i >= 1; i--) {
for (int j = 1; j <= 20; j++) {
if (f[i][j-1] == inf)break;
f[i][j] = f[f[i][j-1]][j-1];
}
}
int qq;
cin >> qq;
while (qq--) {
int a, b;
cin >> a >> b;
if (a > b)swap(a, b);
int ans = 1;
for (int i = 20; i >= 0; i--) {
if (f[a][i] < b) {
a = f[a][i];
ans+=(int)pow(2, i);
}
}
cout << ans << endl;
}
}
signed main() {
//ios::sync_with_stdio(0);
//init();
ll t = 1;//cin >> t;
while (t--)solve();
return 0;
}