QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#181470 | #6327. Count Arithmetic Progression | ucup-team228 | RE | 194ms | 92008kb | C++20 | 9.2kb | 2023-09-16 19:25:09 | 2023-09-16 19:25:10 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#if __SIZEOF_INT128__ >= 16
typedef __int128 LL;
istream& operator>>(istream& in, __int128& a) { int64_t b; in >> b; a = b; return in; }
ostream& operator<<(ostream& out, const __int128 a) {
unsigned __int128 b = a < 0 ? -a : a; char buf[128]; char* c = end(buf); do { --c; *c = "0123456789"[b % 10]; b /= 10; } while (b);
if (a < 0) { --c; *c = '-'; } int64_t len = end(buf) - c; out.rdbuf()->sputn(c, len); return out;
}
#endif
typedef long long ll;
typedef long double ld;
typedef __int128_t LL;
// Redefine epsilon and infinity as necessary. Be mindful of precision errors.
const ld eps = 1e-9, inf = 1e15;
// Basic point/vector struct.
struct Point {
ld x, y;
explicit Point(ld x = 0, ld y = 0) : x(x), y(y) {}
// Addition, substraction, multiply by constant, dot product, cross product.
friend Point operator + (const Point& p, const Point& q) {
return Point(p.x + q.x, p.y + q.y);
}
friend Point operator - (const Point& p, const Point& q) {
return Point(p.x - q.x, p.y - q.y);
}
friend Point operator * (const Point& p, const ld& k) {
return Point(p.x * k, p.y * k);
}
friend ld dot(const Point& p, const Point& q) {
return p.x * q.x + p.y * q.y;
}
friend ld cross(const Point& p, const Point& q) {
return p.x * q.y - p.y * q.x;
}
bool operator==(const Point& ot) const {
return abs(x - ot.x) <= eps && abs(y - ot.y) <= eps;
}
};
// Basic half-plane struct.
struct Halfplane {
// 'p' is a passing point of the line and 'pq' is the direction vector of the line.
Point p, pq;
ld angle;
Halfplane() {}
Halfplane(const Point& a, const Point& b) : p(a), pq(b - a) {
angle = atan2l(pq.y, pq.x);
}
// Check if point 'r' is outside this half-plane.
// Every half-plane allows the region to the LEFT of its line.
bool out(const Point& r) {
return cross(pq, r - p) < -eps;
}
// Comparator for sorting.
bool operator < (const Halfplane& e) const {
return angle < e.angle;
}
// Intersection point of the lines of two half-planes. It is assumed they're never parallel.
friend Point inter(const Halfplane& s, const Halfplane& t) {
ld alpha = cross((t.p - s.p), t.pq) / cross(s.pq, t.pq);
return s.p + (s.pq * alpha);
}
};
// Actual algorithm
vector<Point> hp_intersect(vector<Halfplane>& H) {
Point box[4] = { // Bounding box in CCW order
Point(inf, inf),
Point(-inf, inf),
Point(-inf, -inf),
Point(inf, -inf)
};
for(int i = 0; i<4; i++) { // Add bounding box half-planes.
Halfplane aux(box[i], box[(i+1) % 4]);
H.push_back(aux);
}
// Sort by angle and start algorithm
sort(H.begin(), H.end());
deque<Halfplane> dq;
int len = 0;
for(int i = 0; i < int(H.size()); i++) {
// Remove from the back of the deque while last half-plane is redundant
while (len > 1 && H[i].out(inter(dq[len-1], dq[len-2]))) {
dq.pop_back();
--len;
}
// Remove from the front of the deque while first half-plane is redundant
while (len > 1 && H[i].out(inter(dq[0], dq[1]))) {
dq.pop_front();
--len;
}
// Special case check: Parallel half-planes
if (len > 0 && fabsl(cross(H[i].pq, dq[len-1].pq)) < eps) {
// Opposite parallel half-planes that ended up checked against each other.
if (dot(H[i].pq, dq[len-1].pq) < 0.0)
return vector<Point>();
// Same direction half-plane: keep only the leftmost half-plane.
if (H[i].out(dq[len-1].p)) {
dq.pop_back();
--len;
}
else continue;
}
// Add new half-plane
dq.push_back(H[i]);
++len;
}
// Final cleanup: Check half-planes at the front against the back and vice-versa
while (len > 2 && dq[0].out(inter(dq[len-1], dq[len-2]))) {
dq.pop_back();
--len;
}
while (len > 2 && dq[len-1].out(inter(dq[0], dq[1]))) {
dq.pop_front();
--len;
}
// Report empty intersection if necessary
if (len < 3) return vector<Point>();
// Reconstruct the convex polygon from the remaining half-planes.
vector<Point> ret(len);
for(int i = 0; i+1 < len; i++) {
ret[i] = inter(dq[i], dq[i+1]);
}
ret.back() = inter(dq[len-1], dq[0]);
return ret;
}
const int mod = 998244353;
const int N = 3e5 + 10;
ll l[N], r[N];
LL calc_seg(LL lef, LL rig, LL lef_y, LL rig_y) {
if (lef_y > rig_y) {
swap(lef_y, rig_y);
}
if (lef == rig) {
return rig_y - lef_y + 1;
} else if (lef_y == rig_y) {
return rig - lef + 1;
} else {
LL x = rig - lef;
LL y = rig_y - lef_y;
return __gcd(x, y) + 1;
}
}
LL calc_trap(LL lef, LL rig, LL lef_y, LL rig_y) {
if (lef_y > rig_y) {
swap(lef_y, rig_y);
}
if (lef == rig) {
return rig_y + 1;
} else {
LL s = (rig - lef) * (lef + rig) / 2;
LL bnd = calc_seg(lef, rig, lef_y, rig_y) + lef + rig + rig - lef;
assert(!(bnd & 1));
return s + bnd / 2 + 1;
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
#ifdef LOCAL
freopen("input.txt", "r", stdin);
#endif
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> l[i];
}
for (int i = 1; i <= n; i++) {
cin >> r[i];
}
// n = 3e5;
// for (int i = 1; i <= n; i++) {
// l[i] = 1;
// r[i] = 1'000'000'000'000;
// }
vector<Halfplane> a;
for (int i = 1; i <= n; i++) {
Halfplane upb(Point{1, ld(-i + r[i])}, Point{0, ld(r[i])});
Halfplane lowb(Point{0, ld(l[i])}, Point{1, ld(-i + l[i])});
a.push_back(upb);
a.push_back(lowb);
}
vector<Point> b = hp_intersect(a);
if (b.empty()) {
cout << "0\n";
} else {
int min_pos = 0;
for (int i = 0; i < b.size(); i++) {
if (b[i].x < b[min_pos].x) {
min_pos = i;
}
}
vector<Point> c;
for (int i = min_pos; i < b.size(); i++) {
c.push_back(b[i]);
}
for (int i = 0; i < min_pos; i++) {
c.push_back(b[i]);
}
int max_pos = 0;
for (int i = 0; i < c.size(); i++) {
if (c[i].x > c[max_pos].x) {
max_pos = i;
}
}
vector<Point> lower, upper;
for (int i = 0; i <= max_pos; i++) {
lower.push_back(c[i]);
}
upper.push_back(c[0]);
for (int i = int(c.size()) - 1; i >= max_pos; i--) {
upper.push_back(c[i]);
}
LL ans = 0;
lower.erase(unique(lower.begin(), lower.end()), lower.end());
upper.erase(unique(upper.begin(), upper.end()), upper.end());
for (int i = 0; i + 1 < upper.size(); i++) {
ld lef_ld = upper[i].x + eps;
ld rig_ld = upper[i + 1].x - eps;
LL lef = ceil(lef_ld);
LL rig = floor(rig_ld);
if (lef > rig) {
continue;
}
ld ang = (upper[i + 1].y - upper[i].y) / (upper[i + 1].x - upper[i].x);
LL lef_y = round(upper[i].y + ang * (lef - upper[i].x));
LL rig_y = round(upper[i].y + ang * (rig - upper[i].x));
ans += calc_trap(lef, rig, lef_y, rig_y);
// cout << lef << " " << rig << " " << lef_y << " " << rig_y << " " << calc_trap(lef, rig, lef_y, rig_y) << "\n";
}
for (int i = 0; i < upper.size(); i++) {
auto p = upper[i];
if (abs(p.x - round(p.x)) < eps) {
ans += LL(floor(p.y)) + 1;
// cout << floor(p.y) + 1 << "\n";
}
}
for (int i = 0; i + 1 < lower.size(); i++) {
ld lef_ld = lower[i].x + eps;
ld rig_ld = lower[i + 1].x - eps;
LL lef = ceil(lef_ld);
LL rig = floor(rig_ld);
if (lef > rig) {
continue;
}
ld ang = (lower[i + 1].y - lower[i].y) / (lower[i + 1].x - lower[i].x);
LL lef_y = round(lower[i].y + ang * (lef - lower[i].x));
LL rig_y = round(lower[i].y + ang * (rig - lower[i].x));
ans -= calc_trap(lef, rig, lef_y, rig_y) - calc_seg(lef, rig, lef_y, rig_y);
// cout << lef << " " << rig << " " << lef_y << " " << rig_y << " " << calc_trap(lef, rig, lef_y, rig_y) - calc_seg(lef, rig, lef_y, rig_y) << "\n";
}
for (int i = 0; i < lower.size(); i++) {
auto p = lower[i];
if (abs(p.x - round(p.x)) < eps) {
ans -= LL(floor(p.y));
// cout << floor(p.y) << "\n";
}
}
cout << ans % mod << "\n";
}
#ifdef LOCAL
cout << "\nTime elapsed: " << double(clock()) / CLOCKS_PER_SEC << " s.\n";
#endif
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 5644kb
input:
3 5 5 2 7 6 7
output:
6
result:
ok 1 number(s): "6"
Test #2:
score: 0
Accepted
time: 1ms
memory: 5656kb
input:
4 2 3 1 6 5 6 4 8
output:
0
result:
ok 1 number(s): "0"
Test #3:
score: 0
Accepted
time: 194ms
memory: 92008kb
input:
300000 121398540794 60081434790 252920491076 43666218735 95583832019 21178121624 315727133812 89837170656 138389231466 174687947367 124350262341 108583578309 289629745492 321006985392 301201031648 138149017169 255983300245 138801256482 285614769875 130583757928 261690466826 74624776159 303504239011 ...
output:
2000014
result:
ok 1 number(s): "2000014"
Test #4:
score: -100
Runtime Error
input:
2 1 1 1000000000000 1000000000000