QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#424865#8669. 正方形计数JCY_10 546ms3836kbC++145.4kb2024-05-29 19:11:162024-05-29 19:11:17

Judging History

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

  • [2024-05-29 19:11:17]
  • 评测
  • 测评结果:10
  • 用时:546ms
  • 内存:3836kb
  • [2024-05-29 19:11:16]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using i128 = __int128;
using u128 = unsigned __int128;
template <typename T>
void chkmax(T &x, const T &y) {
  x = max(x, y);
}
template <typename T>
void chkmin(T &x, const T &y) {
  x = min(x, y);
}
ll floor_div(ll x, ll y) { return x >= 0 ? x / y : (x + 1) / y - 1; }
ll ceil_div(ll x, ll y) { return x <= 0 ? x / y : (x - 1) / y + 1; }
struct vector2 {
  ll x, y;
};
istream &operator>>(istream &is, vector2 &u) { return is >> u.x >> u.y; }
ostream &operator<<(ostream &os, const vector2 &u) {
  return os << '(' << u.x << ", " << u.y << ')';
}
vector2 operator+(const vector2 &u, const vector2 &v) {
  return {u.x + v.x, u.y + v.y};
}
vector2 operator-(const vector2 &u, const vector2 &v) {
  return {u.x - v.x, u.y - v.y};
}
vector2 operator*(const vector2 &u, ll k) { return {u.x * k, u.y * k}; }
vector2 operator*(ll k, const vector2 &u) { return {u.x * k, u.y * k}; }
ll operator*(const vector2 &u, const vector2 &v) {
  return u.x * v.y - u.y * v.x;
}
struct ray {
  vector2 p, d;
  ray() = default;
  ray(const vector2 &_p, const vector2 &_d) : p{_p}, d{_d} {}
};
bool inter_is_left(const ray &l1, const ray &l2, const ray &l3) {
  return (l1.d * l2.d) * (l3.d * (l1.p - l3.p)) >= 
         (l1.d * l3.d) * (l2.d * (l1.p - l2.p));
}
bool can_pop(ray l1, ray l2, const ray &l3) {
  if (!(l1.d * l2.d)) return false;
  if (l1.d * l2.d < 0) swap(l1, l2);
  if (l1.d * l3.d < 0 || l3.d * l2.d < 0) return false;
  return inter_is_left(l1, l2, l3);
}
vector<ray> half_plane_inter(const vector<ray> &vec) {
  vector<ray> qu(vec.size());
  int hd = 0, tl = -1;
  for (auto &i : vec) {
    if (hd < tl && can_pop(qu[hd], qu[tl], i)) continue;
    while (hd < tl && can_pop(qu[tl - 1], i, qu[tl])) --tl;
    while (hd < tl && can_pop(qu[hd + 1], i, qu[hd])) ++hd;
    qu[++tl] = i;
  }
  if (tl - hd + 1 <= 2) return {};
  if (qu[hd].d * qu[hd + 1].d <= 0) return {};
  for (auto &i : vec)
    if (!inter_is_left(qu[hd], qu[hd + 1], i)) return {};
  return vector<ray>(qu.begin() + hd, qu.begin() + tl + 1);
}
namespace euclid {
template <typename T>
T qpow(T x, ll y) {
  T ret;
  for (; y; y >>= 1, x = x * x)
    if (y & 1) ret = ret * x;
  return ret;
}
template <typename T>
T solve(ll a, ll b, ll c, ll n, T U, T R) {
  ll m = (a * n + c) / b;
  if (!m) return qpow(R, n);
  return qpow(R, (b - c - 1) / a) * U * 
         solve(b % a, (b - c - a) % a, a, m - 1, R, qpow(R, b / a) * U) * 
         qpow(R, n - (b * m - c - 1) / a);
}
}  // namespace euclid
struct node {
  ll x, y, sum;
  node() : x{}, y{}, sum{} {}
  node(ll _x, ll _y, ll _sum) : x{_x}, y{_y}, sum{_sum} {}
};
node operator*(const node &u, const node &v) {
  return {u.x + v.x, u.y + v.y, u.sum + v.sum + u.x * v.y};
}
ll solve(ll a, ll b, ll c, ll l, ll r) {
  if (b < 0) {
    a = -a;
    b = -b;
    c = -c;
  }
  c += (l - 1) * a;
  r -= l - 1;
  return floor_div(c, b) * r + floor_div(a, b) * (r + 1) * r / 2 + 
         euclid::solve((a % b + b) % b, b, (c % b + b) % b, r, node{1, 0, 0}, node{0, 1, 0}).sum;
}
ll calc(const ray &ry, ll l, ll r, bool flag) {
  return (ry.p.y + 1) * (r - l + 1) + solve(ry.d.y, ry.d.x, -ry.p.x * ry.d.y - flag, l, r);
}
ll calc(vector<ray> vec) {
  vec.emplace_back(vec[0]);
  vec.emplace_back(vec[1]);
  ll ret = 0;
  for (int i = 1; i + 1 < (int)vec.size(); ++i) {
    ray pre = vec[i - 1], cur = vec[i], nxt = vec[i + 1];
    ll qu = pre.d * cur.d, pu = pre.d.x * ((cur.p - pre.p) * cur.d) + pre.p.x * qu;
    ll qv = cur.d * nxt.d, pv = cur.d.x * ((nxt.p - cur.p) * nxt.d) + cur.p.x * qv;
    if (cur.d.x > 0) {
      ll l = ceil_div(pu, qu);
      ll r = (nxt.d.x <= 0 ? floor_div(pv, qv) : ceil_div(pv, qv) - 1);
      if (l <= r) ret -= calc(cur, l, r, true);
    } else if (cur.d.x < 0) {
      ll l = ceil_div(pv, qv);
      ll r = (pre.d.x >= 0 ? floor_div(pu, qu) : ceil_div(pu, qu) - 1);
      if (l <= r) ret += calc(cur, l, r, false);
    }
  }
  return ret;
}
constexpr int MAXN = 12, INF = 0x3f3f3f3f;
int n;
vector2 pt[MAXN];
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cin >> n;
  int mnx = INF, mxx = -INF, mny = INF, mxy = -INF;
  for (int i = 1; i <= n; ++i) {
    cin >> pt[i];
    chkmin(mnx, (int)pt[i].x);
    chkmax(mxx, (int)pt[i].x);
    chkmin(mny, (int)pt[i].y);
    chkmax(mxy, (int)pt[i].y);
  }
  int lim = min(mxx - mnx, mxy - mny);
  reverse(pt + 1, pt + n + 1);
  pt[n + 1] = pt[1];
  ll ans = 0;
  for (int x = 1; x <= lim; ++x) {
    for (int y = 0; x + y <= lim; ++y) {
      vector<ray> vec;
      for (int i = 1; i <= n; ++i) {
        vector2 d = pt[i + 1] - pt[i];
        if (vector2{y, -x} * d > 0 && d * vector2{x, y} >= 0) {
          vec.emplace_back(pt[i], d);
        } else if (vector2{x, y} * d > 0 && d * vector2{-y, x} >= 0) {
          vec.emplace_back(pt[i] - vector2{x, y}, d);
        } else if (vector2{-y, x} * d > 0 && d * vector2{-x, -y} >= 0) {
          vec.emplace_back(pt[i] - vector2{x - y, x + y}, d);
        } else {
          vec.emplace_back(pt[i] + vector2{y, -x}, d);
        }
      }
      vec = half_plane_inter(vec);
      if (!vec.empty()) ans += calc(vec);
    }
  }
  cout << ans << "\n";
  return 0;
}
/*
g++ A.cpp -o A -std=c++14 -O2 -Wall -Wextra -Wshadow -g -fsanitize=address,undefined
*/

Details

Tip: Click on the bar to expand more detailed information

Subtask #1:

score: 10
Accepted

Test #1:

score: 10
Accepted
time: 202ms
memory: 3488kb

input:

4
131 603
131 1828
1919 1828
1919 603

output:

361182910200

result:

ok 1 number(s): "361182910200"

Test #2:

score: 0
Accepted
time: 0ms
memory: 3620kb

input:

4
239 211
239 962
261 962
261 211

output:

1498772

result:

ok 1 number(s): "1498772"

Test #3:

score: 0
Accepted
time: 546ms
memory: 3632kb

input:

4
0 0
0 2000
2000 2000
2000 0

output:

1336001667000

result:

ok 1 number(s): "1336001667000"

Test #4:

score: 0
Accepted
time: 1ms
memory: 3836kb

input:

4
36 771
36 786
672 786
672 771

output:

427720

result:

ok 1 number(s): "427720"

Test #5:

score: 0
Accepted
time: 4ms
memory: 3624kb

input:

4
0 100
100 200
200 100
100 0

output:

34001650

result:

ok 1 number(s): "34001650"

Subtask #2:

score: 0
Runtime Error

Test #6:

score: 0
Runtime Error

input:

3
131 603
131 1828
1919 603

output:


result:


Subtask #3:

score: 0
Runtime Error

Test #11:

score: 0
Runtime Error

input:

8
0 13
4 15
15 15
15 6
13 1
12 0
5 0
0 6

output:


result:


Subtask #4:

score: 0
Skipped

Dependency #3:

0%

Subtask #5:

score: 0
Skipped

Dependency #4:

0%

Subtask #6:

score: 0
Skipped

Dependency #1:

100%
Accepted

Dependency #2:

0%