This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include "nice_lines.h"
#include <bits/stdc++.h>
using namespace std;
using lint = long long;
using ldouble = long double;
const ldouble EPS = 1e-4;
const lint INF = 2.1e8;
const lint MAXV = 1e4;
const lint BASE = 2e4 + 1;
class Line {
public:
ldouble a, b;
ldouble get(ldouble x) { return a * x + b; }
Line(ldouble a, ldouble b) : a(a), b(b) {}
Line(ldouble x1, ldouble y1, ldouble x2, ldouble y2) {
a = (y1 - y2) / (x1 - x2);
b = y1 - a * x1;
}
};
void solve(int subtask_id, int N) {
map<lint, ldouble> memo;
const auto Query = [&](lint y) {
if (memo.count(y)) return memo[y];
return memo[y] = query(BASE, ldouble(y) / 2);
};
const auto IntersectionX = [&](Line l1, Line l2) {
// a1 * x + b1 = a2 * x + b2
// x = (b2 - b1) / (a1 - a2)
return (l2.b - l1.b) / (l1.a - l2.a);
};
const auto OneLine = [&](ldouble x_1, ldouble y_1, ldouble x_2, ldouble y_2, ldouble x_3, ldouble y_3) {
return abs((y_2 - y_1) / (x_2 - x_1) - (y_3 - y_2) / (x_3 - x_2)) < 1e-11;
};
set<lint> changing_points;
map<lint, ldouble> process;
process[2 * (-INF + 0 * BASE)] = Query(2 * (-INF + 0 * BASE));
process[2 * (-INF + 1 * BASE)] = Query(2 * (-INF + 1 * BASE));
// process[2 * (-INF + 2 * BASE)] = Query(2 * (-INF + 2 * BASE));
process[2 * (-INF + 2 * BASE)] = 2 * Query(2 * (-INF + 1 * BASE)) - Query(2 * (-INF + 0 * BASE));
process[2 * (+INF + 0 * BASE)] = Query(2 * (+INF + 0 * BASE));
process[2 * (+INF + 1 * BASE)] = Query(2 * (+INF + 1 * BASE));
// process[2 * (+INF + 2 * BASE)] = Query(2 * (+INF + 2 * BASE));
process[2 * (+INF + 2 * BASE)] = 2 * Query(2 * (+INF + 1 * BASE)) - Query(2 * (+INF + 0 * BASE));
const auto IsChangingPoint = [&](lint y) {
auto it = process.find(y);
if (!OneLine(it->first, it->second,
next(it)->first, next(it)->second,
next(next(it))->first, next(next(it))->second)) {
return false;
}
if (!OneLine(it->first, it->second,
prev(it)->first, prev(it)->second,
prev(prev(it))->first, prev(prev(it))->second)) {
return false;
}
return !OneLine(prev(it)->first, prev(it)->second,
it->first, it->second,
next(it)->first, next(it)->second);
};
auto it = begin(process); it++; it++;
while (next(next(it)) != end(process)) {
lint y = it->first;
if (IsChangingPoint(y)) {
changing_points.emplace(y);
it++;
continue;
}
if (OneLine(it->first, it->second,
next(it)->first, next(it)->second,
next(next(it))->first, next(next(it))->second)) {
it++;
continue;
}
if (OneLine(prev(it)->first, prev(it)->second,
it->first, it->second,
next(it)->first, next(it)->second)) {
it++;
continue;
}
lint isect;
{
auto it0 = prev(it);
auto it1 = it;
auto it2 = next(it);
auto it3 = next(next(it));
lint lo = it1->first + 1;
lint hi = it2->first - 1;
while (lo < hi) {
lint md = (lo + hi) >> 1;
ldouble yprv = it0->second + ((it1->second - it0->second) / (it1->first - it0->first)) * (md - it0->first);
ldouble ynxt = it3->second + ((it2->second - it3->second) / (it2->first - it3->first)) * (md - it3->first);
if (yprv <= ynxt + EPS) {
hi = md;
} else {
lo = md + 1;
}
}
isect = lo;
}
if (process.count(isect) == 0) {
process[isect] = Query(isect);
} else {
process[y + 1] = Query(y + 1);
process[y + 2] = Query(y + 2);
}
it = process.find(y);
}
for (auto y : changing_points) cout << y << ' '; cout << endl;
assert(changing_points.size() == N);
vector<int> answerA, answerB;
for (auto y : changing_points) {
y >>= 1;
// y = ax + b
// x = BASE
// b = y % BASE
lint b = y % BASE;
while (b < -MAXV) b += BASE;
while (b > +MAXV) b -= BASE;
assert((y - b) % BASE == 0);
lint a = (y - b) / BASE;
assert(-MAXV <= a && a <= +MAXV);
assert(-MAXV <= b && b <= +MAXV);
answerA.emplace_back(int(a));
answerB.emplace_back(int(b));
}
return the_lines_are(answerA, answerB);
}
/*
1
17 10000 10000
1 0
2 1
3 2
3 3
4 4
4 3
4 2
4 1
0 1
0 0
0 -1
0 -2
4 -1
4 -2
-4 -4
-10000 -10000
10000 10000
-300060000 -120024 -2 -1 0 1 30005 60011 90017 90018 120018 120019 120021 120022 120023 120024 300060000
1
4 1000 1000
-10000 -10000
-5000 -5000
5000 5000
10000 10000
1
2 1000 1000
-10000 -10000
-5000 -5000
1
2 1000 1000
0 0
0 1
1 - 0.7 * ANS / (10000 - 402) = 0.989133
(1 - 0.989133) * (10000 - 402) / 0.7
ANS = 199
Queries = 551
1 - 0.7 * (551 - 402) / (10000 - 402)
*/
Compilation message (stderr)
nicelines.cpp: In function 'void solve(int, int)':
nicelines.cpp:131:3: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
131 | for (auto y : changing_points) cout << y << ' '; cout << endl;
| ^~~
nicelines.cpp:131:52: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
131 | for (auto y : changing_points) cout << y << ' '; cout << endl;
| ^~~~
In file included from /usr/include/c++/10/cassert:44,
from /usr/include/x86_64-linux-gnu/c++/10/bits/stdc++.h:33,
from nicelines.cpp:3:
nicelines.cpp:132:33: warning: comparison of integer expressions of different signedness: 'std::set<long long int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
132 | assert(changing_points.size() == N);
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~
nicelines.cpp:33:14: warning: variable 'IntersectionX' set but not used [-Wunused-but-set-variable]
33 | const auto IntersectionX = [&](Line l1, Line l2) {
| ^~~~~~~~~~~~~
# | 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... |