1 条题解
-
1
暴力:一步一步往后走,累计L使用就行
稍微好一些:二分去找一步最远
那我们能不能一步多走点,这个可以联想??????=》倍增的去求f[i][j]表示从i出发走j步到达的最远点。
你的一小步,本题的一大步!!!
#include <bits/stdc++.h> using namespace std; const int MAXN = 100000 + 5; const int LOG = 20; // 2^20 > 1e6,覆盖 N=1e5 绝对够 int n, L, q; int x[MAXN]; int dp[MAXN][LOG]; // dp[i][k]:从 i 出发走 2^k 天能到达的最远下标 int pw2[LOG]; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n; for (int i = 1; i <= n; ++i) cin >> x[i]; cin >> L >> q; // 预处理 2^i pw2[0] = 1; for (int i = 1; i < LOG; ++i) pw2[i] = pw2[i - 1] << 1; // dp[i][0]:两指针求“从 i 出发一天内能到的最远点” int t = 1; for (int i = 1; i <= n; ++i) { if (t < i) t = i; // 注意判断顺序,先 t<n,再访问 x[t+1] while (t < n && x[t + 1] - x[i] <= L) ++t; dp[i][0] = t; // 至少 i 自己;若能往右就到 t } // 倍增 for (int k = 1; k < LOG; ++k) { for (int i = 1; i <= n; ++i) { dp[i][k] = dp[ dp[i][k - 1] ][k - 1]; } } // 处理询问 while (q--) { int a, b; cin >> a >> b; if (a > b) swap(a, b); // 只考虑从左到右 int cur = a, ans = 0; // 从大到小尝试跳 2^i 天,保持 dp[cur][i] < b for (int i = LOG - 1; i >= 0; --i) { if (dp[cur][i] < b) { ans += pw2[i]; cur = dp[cur][i]; } } cout << ans + 1 << '\n'; // 最后一步跳到 >= b } return 0; }
- 1
信息
- ID
- 15
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 30
- 已通过
- 13
- 上传者