[ARC060C] 高橋君とホテル / Tak and Hotels

原题链接

  • 题意:给出 \(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;
}

posted @ 2021-03-29 20:30  u_yan  阅读(60)  评论(0编辑  收藏  举报