• 2022杭电多校第三场 K题 Taxi


    题目链接

    Taxi

    题目大意

    给定我们二维平面上的 n n n个点,我们从当前点 ( x , y ) (x, y) (x,y),前往第 i i i个点,会减少花费 m i n ( ( ∣ x − x i ∣ + ∣ y − y i ∣ ) , w i ) min((|x - x_i | + |y - y_i |), w_i) min((xxi+yyi),wi),给定我们 q q q个询问,每次给我们一个二维平面上的一个点,我们需要计算出最大的减少的花费。

    题解

    主要用到了一个神奇的转换,我也没遇到过,比赛的时候我队友告诉我的~
    在这里插入图片描述
    我们需要预处理出来所有点的四个最值,这样计算的时候就可以 O ( 1 ) O(1) O(1)的时间计算出来了。
    我们根据每个点的 w w w值从小到大进行排序,然后二分标号,然后计算出来当前的最大距离 d d d,通过 d d d w w w进行判断,下一步去左边还是右边,需要注意的是我们需要在二分过程中记录最值。具体细节看代码,看代码会好理解一些。

    代码

    #include
    #include
    #include
    #include
    using namespace std;
    #define int long long
    #define IOS ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);
    const int maxn = 100010, inf = 1e18;
    typedef struct node
    {
        int x, y, w;
        bool operator < (const struct node &t) const{
            return w < t.w;
        } 
    }Node;
    Node points[maxn];
    int a[maxn], b[maxn], c[maxn], d[maxn];
    int n, q;
    int sx, sy;
    int res;
    bool check(int mid)
    {
        int t = -inf;
        int w = points[mid].w;
        t = max(t, sx + sy + a[mid]);
        t = max(t, sx - sy + b[mid]);
        t = max(t, -sx + sy + c[mid]);
        t = max(t, -sx - sy + d[mid]);
        res = max(res, min(w, t));
        return w <= t;
    }
    signed main()
    {
        IOS;
        int t; cin >> t;
        while(t --){
            cin >> n >> q;
            for(int i = 0; i < n; i ++){
                int x, y, w; cin >> x >> y >> w;
                points[i] = {x, y, w};
            }
            sort(points, points + n);
            a[n] = b[n] = c[n] = d[n] = -inf;
            for(int i = n - 1; i >= 0; i --){
                a[i] = max(a[i + 1], -points[i].x - points[i].y);
                b[i] = max(b[i + 1], -points[i].x + points[i].y);
                c[i] = max(c[i + 1], points[i].x - points[i].y);
                d[i] = max(d[i + 1], points[i].x + points[i].y);
            }
            while(q --){
                res = -inf;
                cin >> sx >> sy;
                int l = 0, r = n - 1;
                while(l < r){
                    int mid = l + r + 1 >> 1;
                    if(check(mid)) l = mid;
                    else r = mid - 1;;
                }
                check(l);
                cout << res << endl;
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
  • 相关阅读:
    江协科技51单片机学习- p11 Proteus安装模拟51单片机
    mybatis-plus 分页插件
    按摩软件仿东郊到家系统开发,上门预约系统;
    Git指令
    开发一个接口,需要考虑什么
    Java --代理
    ESP8266-Arduino编程实例-VEML6070紫外光传感器驱动
    CompletionService 和 CompletableFuture
    基于注意力机制的多特征融合人脸活体检测
    IIS 80 端口重绑定
  • 原文地址:https://blog.csdn.net/m0_51171995/article/details/126135040