AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 吐槽
  • App
  • 登录/注册

AcWing 293. 开车旅行(Y总思路的精简版)    原题链接    困难

作者: 作者的头像   life0055 ,  2023-09-20 03:39:08 ,  所有人可见 ,  阅读 43


0


本题主要分为两步

  • 求出每个点的最近和次近编号
  • 倍增加速开车过程

第一部分无需改变。第二部分可以更精简一些。

我们发现题目已经规定了就是 $A$ 先开车去次近点, $B$ 后开车去最近点。首先考虑倍增处理每个点走了 $2^j$ 次后去了哪里。

设 $f_{i,j}$ 为从城市 $i$ 出发走了 $2^j$ 步所到的位置。

显然初始化 $f_{i,0}=ga_i$ 第一步就是由 $A$ 走向次近点,接下来下一步就要由 $B$ 走到 最近点。

走两步就相当于 $f_{i,1}$, 因此实际我们需要初始化 $f_{i,1}=gb_{f_{i,0}}$ 这个也是比较好理解的,先由 $A$ 开车走到第一个位置后,然后下一个 $B$ 要去的位置就是此时 $f_{i,0}$ 这个位置下的最近点,即 gb[f[i][0]]

对于其余的 $j\geq 2$ 的情况,倍增处理即可。

for (int i = 1; i <= n; i++) f[i][0] = ga[i];
for (int j = 1; (1 << j) <= n; j++)
{
    for (int i = 1; i <= n; i++)
    {
        if (j == 1) f[i][1] = gb[f[i][0]];
        else f[i][j] = f[f[i][j - 1]][j - 1];
    }
}

然后考虑倍增预处理走了 $2^j$ 步的距离情况。

设 $da_{i,j}$ 为 $A$ 走了 $2^j$ 步的距离, $db_{i,j}$ 同理。

首先考虑初始化问题。

$da_{i,0}=dist(i,ga_i)$ 第一步就是由 $A$ 走,所以直接初始化两点距离即可。

$db_{i,0}=0$, 第一步根本就不是由 $B$ 走的,所以走的距离是 $0$

$da_{i,1} = da_{i,0}$ 走了两步的情况下, $A$ 只参与了第一步,所以就是 $da_{i,0}$

db[i][1]=dist(f[i][0], gb[f[i][0]]) 第二步由 $B$ 参与,他走的距离是 $A$ 第一步到的城市位置,和自己接下来要去的最近点的距离。

对于其余的 $j\geq 2$ 的情况,倍增处理即可。

for (int i = 1; i <= n; i++) da[i][0] = dist(i, ga[i]), db[i][0] = 0;
for (int i = 1; i <= n; i++) da[i][1] = da[i][0], db[i][1] = dist(f[i][0], gb[f[i][0]]);
for (int j = 2; j <= 16; j++)
{
    for (int i = 1; i <= n; i++)
    {
        da[i][j] = da[i][j - 1] + da[f[i][j - 1]][j - 1];
        db[i][j] = db[i][j - 1] + db[f[i][j - 1]][j - 1];
    }
}

完整代码

#include <bits/stdc++.h>
#define ll long long
#define inf 1e12
#define x first
#define y second
using namespace std;
const int N = 1e5 + 5;
typedef pair<ll, int> p;
int n, ga[N], gb[N], f[N][17];
ll h[N], da[N][17], db[N][17];
void init_g()
{
    set<p> s;
    s.insert({inf, 0}), s.insert({inf + 1, 0});
    s.insert({-inf, 0}), s.insert({-inf - 1, 0});
    for (int i = n; i >= 1; i--)
    {
        auto it = s.upper_bound({h[i], i});
        it++;
        vector<p> a;
        for (int k = 0; k < 4; k++) a.push_back(*it), it--;
        ll d1 = inf, d2 = inf;
        int id1 = 0, id2 = 0;
        for (int k = 3; k >= 0; k--)
        {
            if (abs(h[i] - a[k].x) < d1)
            {
                d2 = d1, d1 = abs(h[i] - a[k].x);
                id2 = id1, id1 = a[k].y;
            }
            else if (abs(h[i] - a[k].x) < d2)
            {
                d2 = abs(h[i] - a[k].x);
                id2 = a[k].y;
            }
        }
        ga[i] = id2, gb[i] = id1;
        s.insert({h[i], i});
    }
}
ll dist(int a, int b)
{
    return abs(h[a] - h[b]);
}
void st()
{
    for (int i = 1; i <= n; i++)
    {
        f[i][0] = ga[i];
        f[i][1] = gb[f[i][0]];
        da[i][0] = dist(i, ga[i]), db[i][0] = 0;
        da[i][1] = da[i][0], db[i][1] = dist(f[i][0], gb[f[i][0]]);
    }
    for (int j = 2; (1 << j) <= n; j++)
    {
        for (int i = 1; i <= n; i++)
        {
            f[i][j] = f[f[i][j - 1]][j - 1];
            da[i][j] = da[i][j - 1] + da[f[i][j - 1]][j - 1];
            db[i][j] = db[i][j - 1] + db[f[i][j - 1]][j - 1];
        }
    }
}
void calc(int s, int x, int &la, int &lb)
{
    la = lb = 0;
    for (int i = 16; i >= 0; i--)
    {
        if (f[s][i] && la + lb + da[s][i] + db[s][i] <= x)
        {
            la += da[s][i], lb += db[s][i];
            s = f[s][i];
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> h[i];
    init_g(), st();
    int x0;
    cin >> x0;
    int res = 0, maxh = 0;
    double ans = inf;
    for (int i = 1; i <= n; i++)
    {
        int la, lb;
        calc(i, x0, la, lb);
        double k = lb ? (double) la / lb : inf;
        if (k < ans || k == ans && h[i] > maxh)
        {
            ans = k;
            maxh = h[i];
            res = i;
        }
    }
    cout << res << "\n";
    int m;
    cin >> m;
    while (m--)
    {
        int si, x0;
        cin >> si >> x0;
        int la, lb;
        calc(si, x0, la, lb);
        cout << la << " " << lb << "\n";
    }
    return 0;
}

0 评论

你确定删除吗?
1024
x

© 2018-2023 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息