QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#226161#5060. CirclehockyWA 559ms4580kbC++209.0kb2023-10-25 17:16:182023-10-25 17:16:19

Judging History

你现在查看的是最新测评结果

  • [2023-10-25 17:16:19]
  • 评测
  • 测评结果:WA
  • 用时:559ms
  • 内存:4580kb
  • [2023-10-25 17:16:18]
  • 提交

answer

/*
Author : Hocky Yudhiono
Rab 25 Okt 2023 02:25:01
*/

#pragma GCC optimize("no-stack-protector,O3,unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")

#include "bits/stdc++.h"
using namespace std;

typedef long long LL;
typedef vector<int> vi;
typedef vector<LL> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<LL, LL> PLL;
typedef pair<LL, LL> pll;
typedef long double ld;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define popf pop_front
#define pf push_front
#define popb pop_back
#define pb push_back
#define fi first
#define se second

const int INFMEM = 63;

// Do dir^1 to get reverse direction
const int dx[8] = {0, 0, 1, -1, 1, -1, 1, -1};
const int dy[8] = {1, -1, 0, 0, 1, -1, -1, 1};
const char dch[4] = {'R', 'L', 'D', 'U'};

// Do (dir + 2)%4 to get reverse direction
// const int dx[8] = {-1,0,1,0,-1,1,1,-1};
// const int dy[8] = {0,1,0,-1,1,1,-1,-1};
// const char dch[4] = {'U','R','D','L'};
const double PI = 3.141592653589793;

inline void fasterios() {
  cin.tie(0)->sync_with_stdio(0);
  cin.exceptions(cin.failbit);
}
#define endl '\n'
const int MOD = 1000000007;
// const int MOD = 998244353;

#ifdef _WIN32
#define getchar_unlocked getchar
#endif
#define GETCHAR getchar_unlocked
inline void fastll(LL &input_number) {
  input_number = 0;
  int ch = GETCHAR();
  int sign = 1;
  while (ch < '0' || ch > '9') {
    if (ch == '-') sign = -1;
    ch = GETCHAR();
  }
  while (ch >= '0' && ch <= '9') {
    input_number = (input_number << 3) + (input_number << 1) + ch - '0';
    ch = GETCHAR();
  }
  input_number *= sign;
}

template <class T> int sgn(T x) { return (x > 0) - (x < 0); }
template<class T>
struct Point {
  typedef Point P;
  T x, y;
  explicit Point(T X = 0, T Y = 0) : x(X), y(Y) {}
  bool operator<(P p) const { return tie(x, y) < tie(p.x, p.y); }
  bool operator==(P p) const { return tie(x, y) == tie(p.x, p.y); }
  P operator+(P p) const { return P(x + p.x, y + p.y); }
  P operator-(P p) const { return P(x - p.x, y - p.y); }
  P operator*(T d) const { return P(x * d, y * d); }
  P operator/(T d) const { return P(x / d, y / d); }
  T dot(P p) const { return x * p.x + y * p.y; }
  T cross(P p) const { return x * p.y - y * p.x; }
  T cross(P a, P b) const { return (a - *this).cross(b - *this); }
  // return the orientation of (*this,a,b), 1 if ccw
  int ccw(P a, P b) const { return sgn((a - *this).cross(b - *this)); }
  T dist2() const { return x * x + y * y; }
  double dist() const { return sqrt((double)dist2()); }
  // angle to x-axis in interval [-pi, pi]
  double angle() const { return atan2(y, x); }
  P unit() const { return *this / dist(); } // makes dist()=1
  P perp() const { return P(-y, x); } // rotates +90 degrees
  P normal() const { return perp().unit(); }
  // returns point rotated 'a' radians ccw around the origin
  P rotate(double a) const {
    return P(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a));
  }
  friend ostream& operator<<(ostream& os, P p) {
    return os << "" << p.x << " " << p.y << "";
  }
};

typedef Point<double> P;
typedef double db;
template<class P>
pair<int, P> lineInter(P s1, P e1, P s2, P e2) {
  auto d = (e1 - s1).cross(e2 - s2);
  if (d == 0) // if parallel
    return { -(s1.cross(e1, s2) == 0), P(0, 0)};
  auto p = s2.cross(e1, e2), q = s2.cross(e2, s1);
  return {1, (s1 * p + e1 * q) / d};
}

template<class P>
int sideOf(P s, P e, P p) { return sgn(s.cross(e, p)); }

template<class P>
int sideOf(const P& s, const P& e, const P& p, double eps) {
  auto a = (e - s).cross(p - s);
  double l = (e - s).dist() * eps;
  return (a > l) - (a < -l);
}
typedef array<P, 2> Line;
#define sp(a) a[0], a[1]
#define ang(a) (a[1] - a[0]).angle()

int angDiff(Line a, Line b) { return sgn(ang(a) - ang(b)); }
bool cmp(Line a, Line b) {
  int s = angDiff(a, b);
  return (s ? s : sideOf(sp(a), b[0])) < 0;
}
vector<P> halfPlaneIntersection(vector<Line> &vs) {
  const double EPS = sqrt(2) * 1e-8;
  sort(all(vs), cmp);
  vector<Line> deq(sz(vs) + 5);
  vector<P> ans(sz(vs) + 5);
  deq[0] = vs[0];
  int ah = 0, at = 0, n = sz(vs);
  rep(i, 1, n + 1) {
    if (i == n) vs.push_back(deq[ah]);
    if (angDiff(vs[i], vs[i - 1]) == 0) continue;
    while (ah < at && sideOf(sp(vs[i]), ans[at - 1], EPS) < 0)
      at--;
    while (i != n && ah < at && sideOf(sp(vs[i]), ans[ah], EPS) < 0)
      ah++;
    auto res = lineInter(sp(vs[i]), sp(deq[at]));
    if (res.first != 1) continue;
    ans[at++] = res.second, deq[at] = vs[i];
  }
  if (at - ah <= 2) return {};
  return {ans.begin() + ah, ans.begin() + at};
}

typedef double db;
typedef pair<P, db> Circle;
const double TAU = 2 * PI;

namespace CIRUT {
const int LIM = 1000;
Circle isi[LIM + 18];
int n, p[LIM * 4 + 18], q[LIM * 4 + 18], qt, ttmp;
db ans[LIM + 18], alp[LIM * 4 + 18];
void reset(int _n) {
  n = _n; qt = ttmp = 0;
  rep(i, 0, (n + 1) * 4 + 2) p[i] = q[i] = alp[i] = 0;
  rep(i, 0, n + 1) ans[i] = 0, isi[i] = Circle();
}

int eps(db x) {
  return x < -1e-8 ? -1 : x > 1e-8;
}

int cmpor(const void *i, const void *j) {
  return (ttmp = eps(alp[*(int *)i] - alp[*(int *)j])) ? ttmp : q[*(int *)j] - q[*(int *)i];
}

int judge(db d, int r0, int r1) {
  if (eps(d - r0 - r1) >= 0) return -1;
  if (eps(d + r1 - r0) <= 0) return 0;
  if (eps(d + r0 - r1) <= 0) return 1;
  return 2;
}

void inter(int a, int b, int dx, int dy, db d, db &a0, db &a1) {
  db da = acos((isi[a].se * isi[a].se + d * d - isi[b].se * isi[b].se) * 0.5 / (isi[a].se * d));
  db ba = atan2(dy, dx); a0 = ba - da, a1 = ba + da;
  if (a0 < 0) a0 += TAU;
  if (a1 < 0) a1 += TAU;
}

db calcarea(int a, db a0, db a1) {
  db da = a1 - a0;
  if (!eps(da)) return 0;
  db x0 = isi[a].fi.x + isi[a].se * cos(a0), y0 = isi[a].fi.y + isi[a].se * sin(a0);
  db x1 = isi[a].fi.x + isi[a].se * cos(a1), y1 = isi[a].fi.y + isi[a].se * sin(a1);
  return isi[a].se * isi[a].se * (da - sin(da)) + (x0 * y1 - x1 * y0);
}

void calc(int X) {
  int covered = 1, dx, dy;
  db d; qt = 0;
  for (int i = 1, tmp; i <= n; ++i)
    if (X != i && (dx = isi[i].fi.x - isi[X].fi.x, dy = isi[i].fi.y - isi[X].fi.y, tmp = judge(d = sqrt(dx * dx + dy * dy), isi[X].se, isi[i].se)) > 0) {
      if (tmp == 1) ++covered;
      else {
        inter(X, i, dx, dy, d, alp[qt + 1], alp[qt + 2]);
        q[++qt] = 1, p[qt] = qt;
        q[++qt] = -1, p[qt] = qt;
        if (eps(alp[qt - 1] - alp[qt]) > 0) {
          alp[++qt] = 0, q[qt] = 1, p[qt] = qt;
          alp[++qt] = TAU, q[qt] = -1, p[qt] = qt;
        }
      }
    }
  if (!qt) {ans[covered] += isi[X].se * isi[X].se * TAU; return;}
  qsort(p + 1, qt, sizeof(p[0]), cmpor);
  ans[covered] += calcarea(X, 0, alp[p[1]]) + calcarea(X, alp[p[qt]], TAU);
  for (int i = 1; i < qt; ++i)
    covered += q[p[i]], ans[covered] += calcarea(X, alp[p[i]], alp[p[i + 1]]);
}

void solve() {
  rep(i, 1, n + 1) calc(i);
  rep(i, 1, n + 1) ans[i] -= ans[i + 1], ans[i] *= 0.5;
}
}

// Don't forget to read all the inputs before returning!!!
int solve() {
  LL n; fastll(n);
  LL rr; fastll(rr);
  double r = rr;
  vector <P> isi(n);
  trav(cur, isi) {
    LL a; fastll(a);
    LL b; fastll(b);
    cur.x = a;
    cur.y = b;
  }
  if (n <= 20) {
    // Solve using cirut
    CIRUT::reset(n + 1);
    for (int i = 1; i <= n; i++) {
      CIRUT::isi[i] = {isi[i - 1], r};
    }
    CIRUT::solve();
    printf("%.9f\n", CIRUT::ans[n]);
    return 0;
  }
  vector <Line> halfplane;
  rep(i, 0, n) {
    // make a circle with radius r
    auto &cur = isi[i];
    auto &nx = isi[(i + 1) % n];
    db dist = (cur - nx).dist() / 2;
    if (fabs(dist / r) >= 1) {
      cout << 0 << endl;
      return 0;
    }
    auto alpha = acos(dist / r);
    if (isnan(alpha)) {
      cout << 0 << endl;
      return 0;
    }
    //masukin 4 kotak
    // Kotak kanan
    {
      auto vec1 = nx - cur;
      auto pvec1 = vec1.perp();
      vec1 = vec1.unit() * r + cur;
      halfplane.pb({vec1, vec1 + pvec1});
    }
    // // Kotak kiri
    {
      auto vec1 = cur - nx;
      auto pvec1 = vec1.perp();
      vec1 = vec1.unit() * r + nx;
      halfplane.pb({vec1, vec1 + pvec1});
    }
    auto vec = (nx - cur);
    auto center1 = cur + vec.rotate(alpha).unit() * r;
    auto center2 = cur + vec.rotate(-alpha).unit() * r;
    halfplane.pb({center1, center1 + (cur - nx)});
    halfplane.pb({center2, center2 + (nx - cur)});
    // cout << center2 << endl;
  }
  auto res = halfPlaneIntersection(halfplane);
  double ans = 0;
  rep(i, 0, sz(res)) {
    ans += res[i].cross(res[(i + 1) % sz(res)]);
  }
  printf("%.9f\n", ans);
  // cout << (ans) / 2 << '\n';
  return 0;
}

int main() {
  LL testCases = 1, tc = 0;
  fastll(testCases);
  while (++tc <= testCases) {
    // cout << "Case #" << tc << ": ";
    solve();
  }
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 4060kb

input:

3
4 1
0 0
1 0
1 1
0 1
4 1
0 0
1 1
0 2
-1 1
4 100
0 0
1 0
1 1
0 1

output:

0.315146744
0.000000000
31016.928202571

result:

ok 3 numbers

Test #2:

score: 0
Accepted
time: 108ms
memory: 3676kb

input:

200000
1 2
616 2935
1 3
1708 -4771
1 4
4133 2145
1 5
3093 -8563
1 6
-6703 -7258
1 7
-8847 -6629
1 8
-9278 -3604
1 9
3958 -8464
1 10
-7019 4795
1 11
-4181 4366
1 12
-8801 -3294
1 13
-8106 -4512
1 14
-7044 1933
1 15
-5546 -9705
1 16
2755 -6889
1 17
5578 -2779
1 18
3724 -6647
1 19
6530 4628
1 20
-9775 ...

output:

12.566370614
28.274333882
50.265482457
78.539816340
113.097335529
153.938040026
201.061929830
254.469004941
314.159265359
380.132711084
452.389342117
530.929158457
615.752160104
706.858347058
804.247719319
907.920276887
1017.876019763
1134.114947946
1256.637061436
1385.442360233
1520.530844337
1661....

result:

ok 200000 numbers

Test #3:

score: 0
Accepted
time: 181ms
memory: 4280kb

input:

49788
1 1
1 1
2 2
-1 -2
2 0
3 7
-1 -2
3 -1
-1 0
3 11
1 -3
4 -2
4 3
4 4
-3 4
-2 1
5 0
3 3
5 3
-6 1
-5 -5
4 -6
5 -2
2 0
6 13
-6 -2
5 -4
6 -4
7 3
5 5
-3 1
7 13
-8 -2
-2 -7
3 -8
8 -8
7 -4
3 -1
-8 4
6 22
-8 -1
-7 -8
-6 -9
7 -8
6 0
1 7
5 29
-9 0
-3 -10
3 -8
5 6
-3 9
1 1
0 1
2 3
0 -1
1 2
3 5
-1 1
1 -1
2 3
...

output:

3.141592654
0.460160176
87.107972627
225.814739058
0.000000000
0.000000000
150.180118660
65.330022402
589.961772321
1331.375887990
3.141592654
10.219895118
31.943872526
19.970661395
0.000000000
8.492873198
200.610225250
631.162631043
667.620777787
1.952409257
12.566370614
6.194964160
0.000000000
19....

result:

ok 49788 numbers

Test #4:

score: -100
Wrong Answer
time: 559ms
memory: 4580kb

input:

236
832 25032
-9981 -8425
-9980 -8477
-9979 -8527
-9975 -8619
-9968 -8777
-9956 -8917
-9948 -8993
-9932 -9112
-9910 -9242
-9907 -9258
-9898 -9298
-9887 -9337
-9857 -9438
-9851 -9457
-9819 -9545
-9812 -9559
-9774 -9627
-9745 -9678
-9729 -9699
-9702 -9734
-9671 -9754
-9637 -9772
-9544 -9819
-9534 -982...

output:

1491433677.231539965
155805915.346982777
271047093.292943120
0.000000000
0.000000000
0.000000000
1415943878.095309258
30497489.490461685
0.000000000
0.000000000
0.000000000
0.000000000
0.000000000
0.000000000
0.000000000
2675057441.702635765
0.000000000
0.000000000
0.000000000
1228667907.094140291
0...

result:

wrong answer 1st numbers differ - expected: '615624863.1877460', found: '1491433677.2315400', error = '1.4226339'