题目
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=107574#problem/E
题目来源:2016.2.26群赛
简要题意:给定雪橇的垂直速度和固定的水平速度,给定一些门的左右区间和 y 坐标。
求能够穿过所有门的雪橇中速度最快的,不可能则特殊输出。
题解
由于存在单调性,可以对雪橇速度去排序然后二分。
维护可以到达的左右区间,根据两个门之间的距离和垂直速度可以推出水平移动最远多少。
最左最远是上一轮最左减去最远水平距离,最右是上一轮最优加上最远水平距离。
再根据门去取个最值即可,然后判断 l⩽r 。
代码
#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;
}