HBCPC 2020 phobia
题目
People with social phobia hate the moment when meeting some acquaintances on the street. So they will try to avoid any chance of making such things happen.
Though hate sudden encounters, people with social phobia still can't stay at home all the time. In order to keep physical health, they will take walks from time to time. The position of each one's house is known, which can be seen as a point on a number axis. We also learned that everyone will move at a constant speed when they take walks.
Now you are given the positions of their houses and their walking speed, and you are able to choose and order k persons to stay home. Your task is to find out, if the remaining persons start to take walks at the same time, for how long at most they can walk without meeting anyone?
Input Format
The first line contains two integers n,k(1≤n≤105,0≤k≤n), the total number of persons and the number of persons you can order to stay home.
Then n lines follow, each line contains two integers x,v(∣x∣,∣v∣≤109), denoting one person's starting position and walking speed.
It is guaranteed that at the beginning there can be only at most one person at each position of the number axis .
Output Format
Print one decimal number, the longgest time they may walk without meeting anyone. If they may keep walking forever without meeting anyone, print -1
. Your answer is considered correct if the relative or absolute error is below 10−4.
Sample Input
-1
代码长度限制
16 KB
时间限制
5000 ms
内存限制
512 MB
思路
按初始位置给每个人排序, 经过 \(t\)秒后, 在给每个人排序, 每个人的编号不变, 问我们抹去多少个编号能够使该序列升序,显然等于\(n - siz(LIS)\), LIS (最长上升子序列), 我们对时间二分,显然答案满足二段性, 如下图:
总复杂度\(O(nlog^2n)\)
Code
#include <bits/stdc++.h>
#define ff first
#define ss second
using i64 = long long;
const int N = 1e5 + 10;
const double EPS = 1e-6;
typedef std::pair<i64, i64> PII;
struct node {
int id;
double pos, v, ipos;
bool operator<(const node t) const {
if (pos == t.pos) {
return id > t.id;
}
return pos < t.pos;
}
};
int n, k;
node a[N];
/*
check O(nlogn)
binary-search O(logn) calculate LIS
--> nlog^2n
*/
bool check(double time) {
static int stk[N];
int len = 0;
for (int i = 1; i <= n; i ++) {
a[i].pos = a[i].ipos + time * a[i].v;
}
std::sort(a + 1, a + 1 + n);
stk[0] = -1e9;
for (int i = 1; i <= n; i ++) {
int l = 0, r = len;
while (l < r) {
int mid = l + r + 1 >> 1;
if (stk[mid] < a[i].id) l = mid;
else r = mid - 1;
}
stk[l + 1] = a[i].id;
len = std::max(len, l + 1);
}
return n - len <= k;
}
int main() {
std::cin >> n >> k;
for (int i = 1; i <= n; i ++) {
std::cin >> a[i].pos >> a[i].v;
a[i].ipos = a[i].pos;
}
std::sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i ++) {
a[i].id = i;
}
double l = 0, r = 2e9 + 10;
int cnt = 1;
while (r - l > EPS) {
double mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
if (r == 2e9 + 10) {
std::cout << -1;
} else {
printf("%.4lf", l);
}
}