This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// https://oj.uz/problem/view/BOI12_mobile
#include <bits/stdc++.h>
using namespace std;
#define forint(i, from, toinc) for (int i = from; i <= toinc; ++i)
#define sq(x) (x)*(x)
#define all(x) x.begin(), x.end()
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
#ifdef USEFILE
freopen("mobile.in", "r", stdin);
freopen("mobile.out", "w", stdout);
#endif
}
/*
some observations:
if we have 2 towers with the same x, (x, y1) and (x, y2),
we only need to keep the one with the smallest abs y value,
let's say |y1| <= |y2|, then we can safely forget (x, y2), because for any
point on the x axis, it will always be closer (<=) to (x, y1) than to (x, y2).
we do a simple binary search on distance d to see if all points between [0,L]
can be covered by d.
when trying to see if the segments covers the entire [0,len] range,
we do NOT have to sort the segments, because if a later one (one corresponding
to a tower with greater x value) connects with the current range
while a earlier one does not, we know from geometry that the later one
will extend further to the right as well, making not considering the earlier one
inconsequential. but this time, don't break when seeing a gap.
*/
struct Point {
int x,y;
};
struct Range {
double from, to;
bool operator<(const Range &o) const {
return from == o.from ? to > o.to : from < o.from;
// same from rank the one with the larger to first
}
};
int tcnt; // tower count
vector<Point> towers;
int len; // all points on (0,0) to (len,0) to the towers
vector<Range> ranges;
int rcnt;
void debug()
{
cerr << "highway from (0,0) to (" << len << ",0)" << endl;
cerr << tcnt << " towers:";
forint(i, 0, tcnt-1) {
cerr << " " << towers[i].x << "," << towers[i].y;
}
cerr << endl;
cerr << rcnt << " ranges:";
forint(i, 0, rcnt-1) {
cerr << " [" << ranges[i].from << "," << ranges[i].to << "]";
}
cerr << endl;
}
void rdata()
{
cin >> tcnt >> len;
int lastx, lasty; // lasty >= 0
cin >> lastx >> lasty;
lasty = abs(lasty);
forint(i, 1, tcnt-1) {
int x, y;
cin >> x >> y;
if (x != lastx) {
towers.push_back({lastx, lasty});
lastx = x;
lasty = abs(y);
} else if (abs(y) < abs(lasty)) {
lasty = abs(y);
}
if (i == tcnt-1) {
towers.push_back({lastx, lasty});
}
}
tcnt = (int)towers.size();
}
bool can_cover(double d)
{
ranges.clear();
forint(i, 0, tcnt-1) {
double x = towers[i].x;
double y = towers[i].y;
if (d > y) {
double dx = sqrt(sq(d) - sq(y));
if (x-dx > len || x+dx < 0) continue;
ranges.push_back({x-dx, x+dx});
}
}
rcnt = (int)ranges.size();
// sort(all(ranges));
#ifdef DEBUG
debug();
#endif
double right = 0;
forint(i, 0, rcnt-1) {
if (ranges[i].from <= right) {
right = max(ranges[i].to, right);
if (right >= len) break;
}
}
bool res = right >= len;
#ifdef DEBUG
cerr << "d=" << d << " can" << (res ? "" : "not") << " cover all" << endl;
#endif
return res;
}
inline
double d2(int i, double x) // tower i to (x,0)
{
return sq(towers[i].x - x) + sq(towers[i].y);
}
int main()
{
fio();
rdata();
#ifdef DEBUG
debug();
#endif
double dends2 = d2(0, 0);
dends2 = max(dends2, d2(0, len));
dends2 = max(dends2, d2(tcnt-1, 0));
dends2 = max(dends2, d2(tcnt-1, len));
double dmax = sqrt(dends2);
double d = dmax+1;
for (double step = dmax; step > 1e-4; step /= 2) {
while (d-step > 0 && can_cover(d-step)) {
d -= step;
}
}
cout << fixed << setprecision(3) << d << '\n';
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |