QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#92048#4515. TrianglesKHIN50 ✓1231ms3720kbC++1712.1kb2023-03-30 09:44:482023-03-30 09:44:52

Judging History

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

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-03-30 09:44:52]
  • 评测
  • 测评结果:50
  • 用时:1231ms
  • 内存:3720kb
  • [2023-03-30 09:44:48]
  • 提交

answer

# include <cstdlib>
# include <tuple>
# include <type_traits>
# include <cassert>
# include <vector>
# include <algorithm>
# include <numeric>
# include <cstdio>
# include <iostream>
# include <istream>
# include <ostream>

namespace khin {
  using namespace std;
  namespace main {
    inline namespace source {
      template <typename T, enable_if_t<is_signed_v<T>, int> = 0>
        int sgn(T const value) { return (value > 0) - (value < 0); }
    }
    namespace a { void main(); }
    namespace b { void main(); }
    namespace c { void main(); }
    namespace d { void main(); }
    namespace e { void main(); }
  }
}

int main() { khin::main::e::main(); }

namespace khin::main::e {
  namespace test_case {
    struct vector {
      long x, y;
      constexpr vector() : x(), y() {}
      explicit constexpr vector(long const x, long const y) : x(x), y(y) {}
      constexpr vector operator+() const { return vector(+x, +y); }
      constexpr vector operator-() const { return vector(-x, -y); }
      constexpr friend vector operator+(vector const u, vector const v)
      { return vector(u.x + v.x, u.y + v.y); }
      constexpr friend vector operator-(vector const u, vector const v)
      { return vector(u.x - v.x, u.y - v.y); }
      constexpr friend long operator*(vector const u, vector const v)
      { return u.x * v.y - u.y * v.x; }
    } typedef point;
    constexpr uint n_max(3'000);
    uint n; point p[n_max + 1]; std::vector<uint> s, t;
    std::vector<tuple<uint, uint, uint>> ans;
    void main(ushort const x) {
      cin >> n;
      for (uint i(1); i <= n; ++i) cin >> p[i].x >> p[i].y;
      s.resize(n), iota(s.begin(), s.end(), 1u);
      while (s.size() >= 3) {
        uint a, b, c; decltype(s)::iterator it;
        auto const cmp0 = [] (uint const i, uint const j)
        { return make_pair(p[i].x, p[i].y) < make_pair(p[j].x, p[j].y); };
        auto const cmp1 = [&a] (uint const i, uint const j) {
          vector const u(p[i] - p[a]), v(p[j] - p[a]);
          if (u * v) return u * v > 0;
          else return abs(u.x) + abs(u.y) < abs(v.x) + abs(v.y);
        };
        auto const cmp2 = [&b] (uint const i, uint const j) {
          vector const u(p[i] - p[b]), v(p[j] - p[b]);
          if (u * v) return u * v < 0;
          else return abs(u.x) + abs(u.y) < abs(v.x) + abs(v.y);
        };
        a = *(it = min_element(s.begin(), s.end(), cmp0)), s.erase(it);
        b = *(it = min_element(s.begin(), s.end(), cmp1)), s.erase(it);
        c = *(it = min_element(s.begin(), s.end(), cmp2)), s.erase(it);
        if ((p[a] - p[b]) * (p[b] - p[c])) ans.emplace_back(a, b, c);
        else { s.push_back(a), s.push_back(b), s.push_back(c); break; }
      }
      while (s.size() % 3) s.pop_back();
      /* fprintf(stderr, "%s %u (%zu)\n", __func__, __LINE__, ans.size()); */
      if (!s.empty()) {
        /*
           fprintf(stderr, "%s %u ", __func__, __LINE__);
           fprintf(stderr, "(%zu) ", ans.size());
           fprintf(stderr, "(%zu %zu)\n", s.size(), t.size());
         */
        while (2 * t.size() < s.size() && !ans.empty()) {
          auto const [a, b, c](ans.back()); ans.pop_back();
          ((p[a] - p[s[0]]) * (p[a] - p[s[1]]) ? t : s).push_back(a);
          ((p[b] - p[s[0]]) * (p[b] - p[s[1]]) ? t : s).push_back(b);
          ((p[c] - p[s[0]]) * (p[c] - p[s[1]]) ? t : s).push_back(c);
        }
        /*
           fprintf(stderr, "%s %u ", __func__, __LINE__);
           fprintf(stderr, "(%zu) ", ans.size());
           fprintf(stderr, "(%zu %zu)\n", s.size(), t.size());
         */
        while (s.size() > 2 * t.size()) s.pop_back();
        /*
           fprintf(stderr, "%s %u ", __func__, __LINE__);
           fprintf(stderr, "(%zu) ", ans.size());
           fprintf(stderr, "(%zu %zu)\n", s.size(), t.size());
         */
        assert(2 * t.size() == s.size() || 2 * t.size() == s.size() + 3);
        /*
           fprintf(stderr, "%s %u ", __func__, __LINE__);
           fprintf(stderr, "(%zu) ", ans.size());
           fprintf(stderr, "(%zu %zu)\n", s.size(), t.size());
         */
        if (s.empty() && !t.empty())
          ans.emplace_back(t[0], t[1], t[2]), t.clear();
        [] {
          auto const comp = [] (uint const i, uint const j)
          { return make_pair(p[i].x, p[i].y) < make_pair(p[j].x, p[j].y); };
          sort(s.begin(), s.end(), comp);
        } ();
        if (!s.empty()) {
          vector const d(p[s[1]] - p[s[0]]);
          for (uint const i : s) assert(!((p[i] - p[s.back()]) * d));
          for (uint const i : t) assert( ((p[i] - p[s.back()]) * d));
          while (assert(s.empty() == t.empty()), !s.empty()) {
            assert(2 * t.size() == s.size() || 2 * t.size() == s.size() + 3);
            if (2 * t.size() == s.size()) {
              uint const a(s.back()); s.pop_back();
              uint const b(s.back()); s.pop_back();
              auto const comp = [&b, d] (uint const i, uint const j) {
                vector const u(p[i] - p[b]); assert(u * d);
                vector const v(p[j] - p[b]); assert(v * d);
                if (sgn(u * d) != sgn(v * d)) return sgn(u * d) < sgn(v * d);
                else if (u * v) return sgn(u * d) * (u * v) < 0;
                else return abs(u.x) + abs(u.y) < abs(v.x) + abs(v.y);
              };
              auto const it(min_element(t.begin(), t.end(), comp));
              uint const c(*it); t.erase(it);
              assert((p[a] - p[b]) * (p[b] - p[c]));
              ans.emplace_back(a, b, c);
              continue;
            }
            if (s.size() == 1) {
              /* fprintf(stderr, "case %s %u\n", __func__, __LINE__); */
              assert(t.size() == 2);
              ans.emplace_back(s[0], t[0], t[1]);
              s.clear(), t.clear();
              continue;
            }
            uint pos(0), neg(0);
            for (uint const i : t) switch (sgn((p[i] - p[s.back()]) * d)) {
              case +1: ++pos; break;
              case -1: ++neg; break;
              default: assert(false);
            }
            if (pos && pos == min(pos, neg)) {
              [d] {
                uint const a(s.back()); s.pop_back();
                uint const b(s.back()); s.pop_back();
                auto const comp = [&b, d] (uint const i, uint const j) {
                  vector const u(p[i] - p[b]); assert(u * d);
                  vector const v(p[j] - p[b]); assert(v * d);
                  if (sgn(u * d) != sgn(v * d)) return u * d > v * d;
                  else if (u * v) return sgn(u * d) * (u * v) < 0;
                  else return abs(u.x) + abs(u.y) < abs(v.x) + abs(v.y);
                };
                auto const it(min_element(t.begin(), t.end(), comp));
                uint const c(*it); t.erase(it);
                assert((p[a] - p[b]) * (p[b] - p[c]));
                ans.emplace_back(a, b, c);
              } ();
              continue;
            }
            if (neg && neg == min(pos, neg)) {
              [d] {
                uint const a(s.back()); s.pop_back();
                uint const b(s.back()); s.pop_back();
                auto const comp = [&b, d] (uint const i, uint const j) {
                  vector const u(p[i] - p[b]); assert(u * d);
                  vector const v(p[j] - p[b]); assert(v * d);
                  if (sgn(u * d) != sgn(v * d)) return u * d < v * d;
                  else if (u * v) return sgn(u * d) * (u * v) < 0;
                  else return abs(u.x) + abs(u.y) < abs(v.x) + abs(v.y);
                };
                auto const it(min_element(t.begin(), t.end(), comp));
                uint const c(*it); t.erase(it);
                assert((p[a] - p[b]) * (p[b] - p[c]));
                ans.emplace_back(a, b, c);
              } ();
              continue;
            }
            if (pos && neg) {
              uint const a(s.back()); s.pop_back();
              auto const cmp0 = [&a, d] (uint const i, uint const j) {
                vector const u(p[i] - p[a]); assert(u * d);
                vector const v(p[j] - p[a]); assert(v * d);
                if (sgn(u * d) != sgn(v * d)) return sgn(u * d) > sgn(v * d);
                else if (u * v) return sgn(u * d) * (u * v) < 0;
                else return abs(u.x) + abs(u.y) < abs(v.x) + abs(v.y);
              };
              auto const cmp1 = [&a, d] (uint const i, uint const j) {
                vector const u(p[i] - p[a]); assert(u * d);
                vector const v(p[j] - p[a]); assert(v * d);
                if (sgn(u * d) != sgn(v * d)) return sgn(u * d) < sgn(v * d);
                else if (u * v) return sgn(u * d) * (u * v) < 0;
                else return abs(u.x) + abs(u.y) < abs(v.x) + abs(v.y);
              };
              decltype(t)::iterator it;
              uint const b(*(it = min_element(t.begin(), t.end(), cmp0)));
              t.erase(it);
              uint const c(*(it = min_element(t.begin(), t.end(), cmp1)));
              t.erase(it);
              ans.emplace_back(a, b, c);
              assert((p[a] - p[b]) * (p[b] - p[c]));
              continue;
            }
            if (s.size() > 3) {
              uint const a(s.back()); s.pop_back();
              uint const b(s.back()); s.pop_back();
              auto const comp = [&b, d] (uint const i, uint const j) {
                vector const u(p[i] - p[b]); assert(u * d);
                vector const v(p[j] - p[b]); assert(v * d);
                if (u * v) return sgn(u * d) * (u * v) < 0;
                else return abs(u.x) + abs(u.y) < abs(v.x) + abs(v.y);
              };
              auto const it(min_element(t.begin(), t.end(), comp));
              uint const c(*it); t.erase(it);
              ans.emplace_back(a, b, c);
              continue;
            }
            assert(s.size() == 3), assert(t.size() == 3);
            auto const chk0 = [d] {
              auto const comp = [d] (uint const i, uint const j) {
                vector const u(p[i] - p[s[0]]); assert(u * d);
                vector const v(p[j] - p[s[0]]); assert(v * d);
                return sgn(u * d) * (u * v) > 0;
              };
              sort(t.begin(), t.end(), comp);
              return comp(t[0], t[1]);
            };
            auto const chk1 = [d] {
              auto const comp = [d] (uint const i, uint const j) {
                vector const u(p[i] - p[s[2]]); assert(u * d);
                vector const v(p[j] - p[s[2]]); assert(v * d);
                return sgn(u * d) * (u * v) < 0;
              };
              sort(t.begin(), t.end(), comp);
              return comp(t[0], t[1]);
            };
            if (chk0()) {
              /* fprintf(stderr, "case %s %u\n", __func__, __LINE__); */
              ans.emplace_back(s[0], t[0], t[1]);
              ans.emplace_back(s[1], s[2], t[2]);
              s.clear(), t.clear();
              continue;
            }
            if (chk1()) {
              /* fprintf(stderr, "case %s %u\n", __func__, __LINE__); */
              ans.emplace_back(s[2], t[0], t[1]);
              ans.emplace_back(s[1], s[0], t[2]);
              s.clear(), t.clear();
              continue;
            }
            /* fprintf(stderr, "case %s %u\n", __func__, __LINE__); */
            auto const comp = [d] (uint const i, uint const j) {
              vector const u(p[i] - p[s[0]]); assert(u * d);
              vector const v(p[j] - p[s[0]]); assert(v * d);
              if (u * v) return sgn(u * d) * (u * v) > 0;
              else return abs(u.x) + abs(u.y) < abs(v.x) + abs(v.y);
            };
            sort(t.begin(), t.end(), comp);
            ans.emplace_back(s[0], s[2], t[1]);
            ans.emplace_back(s[1], t[0], t[2]);
            s.clear(), t.clear();
            continue;
          }
        }
      }
      assert(s.empty()), assert(t.empty());
      printf("Case #%hu: %zu\n", x, ans.size());
      for (auto const [p, q, r] : ans) printf("%u %u %u\n", p, q, r);
      ans.clear();
    }
  }
  void main() {
    ushort t; cin >> t;
    for (ushort i(1); i <= t; ++i) test_case::main(i);
  }
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 8
Accepted
time: 4ms
memory: 3592kb

input:

100
10
220238472 224691753
770968360 1070897
222060078 225731229
213423928 -699125511
571809960 -531790999
-29325160 82281481
523892900 397968241
134123366 175551277
-48116654 71558357
79192162 144205493
6
-800120306 681957950
-800120120 681958048
-800120239 681957972
-800120068 681958102
-800120280...

output:

Case #1: 3
9 4 6
10 5 8
1 2 3
Case #2: 2
1 3 5
6 2 4
Case #3: 4
11 12 7
4 3 8
6 10 9
1 2 5
Case #4: 0
Case #5: 2
2 3 5
1 6 4
Case #6: 3
1 4 7
9 5 2
8 3 6
Case #7: 2
7 6 4
3 1 2
Case #8: 3
2 7 1
10 9 6
3 8 4
Case #9: 4
11 3 9
4 5 2
12 6 10
8 1 7
Case #10: 2
4 5 1
3 6 2
Case #11: 4
11 5 8
9 12 10
3 6 ...

result:

ok  (100 test cases)

Test #2:

score: 42
Accepted
time: 1231ms
memory: 3720kb

input:

100
3000
-92089322 -224238223
-92147554 -225776486
-91601000 -225100640
-92024176 -225644144
-90703509 -224917680
-89202055 -225283952
-92681755 -224149407
-92347180 -225441739
-92259568 -225588653
-91979455 -224254694
-92673281 -224244242
-92527577 -224172521
-90804449 -224883170
-92641474 -2249482...

output:

Case #1: 1000
2743 1593 436
169 1759 2938
2812 2792 2457
46 624 2409
2863 424 999
1335 2697 238
311 2919 1095
1332 1523 787
1515 1042 534
1830 2114 1336
2496 916 275
2666 2023 1297
1693 2755 2234
2685 533 589
1087 2993 1182
2173 2386 2184
1185 2878 1958
2232 764 2584
235 1570 2911
747 2850 1713
57 2...

result:

ok  (100 test cases)