UVA 11627 Slalom 二分 模拟

题目

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=107574#problem/E

题目来源:2016.2.26群赛

简要题意:给定雪橇的垂直速度和固定的水平速度,给定一些门的左右区间和 y 坐标。
    求能够穿过所有门的雪橇中速度最快的,不可能则特殊输出。

题解

由于存在单调性,可以对雪橇速度去排序然后二分。

维护可以到达的左右区间,根据两个门之间的距离和垂直速度可以推出水平移动最远多少。

最左最远是上一轮最左减去最远水平距离,最右是上一轮最优加上最远水平距离。

再根据门去取个最值即可,然后判断 lr

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
// head
const int N = 1e5+5;
const int M = 1e6+5;

PII a[N];
int b[M];

int t, w, h, n, m;

bool ck(int x) {
    double l = a[0].fi, r = a[0].fi + w;
    for (int i = 1; i < n && l <= r; i++) {
        double dis = double(a[i].se - a[i-1].se) * h / x;
        l = max(l - dis, (double)a[i].fi);
        r = min(r + dis, (double)(a[i].fi + w));
    }
    return l <= r;
}

int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d%d", &w, &h, &n);
        for (int i = 0; i < n; i++) {
            scanf("%d%d", &a[i].fi, &a[i].se);
        }

        scanf("%d", &m);
        for (int i = 0; i < m; i++) {
            scanf("%d", b+i);
        }
        sort(b, b + m);
        m = unique(b, b + m) - b;

        int l = 0, r = m-1, ans = -1;
        while (l <= r) {
            int mid = (l+r) / 2;
            if (ck(b[mid])) {
                ans = mid;
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }

        if (ans == -1) {
            puts("IMPOSSIBLE");
        } else {
            printf("%d\n", b[ans]);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值