Submission #956279

#TimeUsernameProblemLanguageResultExecution timeMemory
956279chrisvilchesDragon 2 (JOI17_dragon2)C++14
60 / 100
4054 ms3672 KiB
#include <bits/stdc++.h>
using namespace std;

struct Point {
  int x, y, idx;
  Point operator-(const Point& p) const { return {x - p.x, y - p.y, idx}; }
  Point operator+(const Point& p) const { return {x + p.x, y + p.y, idx}; }
  long long cross(const Point& p) const {
    return x * (long long)p.y - y * (long long)p.x;
  }

  Point negate() const { return {-x, -y, idx}; }
};

short orientation(const Point& o, const Point& a, const Point& b) {
  const long long x = (a - o).cross(b - o);
  return (x > 0) - (x < 0);
}

Point A, B;

bool above(const Point& p) { return B.cross(p) > 0; }

Point to_upper(const Point& p) { return above(p) ? p : p.negate(); }
bool operator<(const Point& p, const Point& q) {
  return to_upper(p).cross(to_upper(q)) > 0;
}

bool cmp_by_b(const Point& p, const Point& q) {
  const bool a1 = above(p);
  const bool a2 = above(q);
  if (a1 != a2) return a1;
  return p.cross(q) > 0;
}

const int bit_n = 30'001;
short bit[bit_n];

void clear(const int n) { memset(bit, 0, sizeof(short) * n); }

int sum(int r) {
  int ret = 0;
  for (; r >= 0; r = (r & (r + 1)) - 1) ret += bit[r];
  return ret;
}

int sum(int l, int r) { return sum(r) - sum(l - 1); }

void add(int idx, const short delta) {
  for (; idx < bit_n; idx = idx | (idx + 1)) bit[idx] += delta;
}

int query(const vector<Point>& points1, const vector<Point>& points2,
          const vector<Point>& ord_b) {
  if (points1.empty() || points2.empty()) return 0;

  clear(points2.size());

  int total = 0;
  int j = 0;

  for (const auto& q : points2) {
    if (!above(q)) add(q.idx, 1);
  }

  for (const Point& p : points1) {
    while (j < (int)points2.size()) {
      const Point& q = points2[j];

      if (p < q) break;
      add(q.idx, above(q) ? 1 : -1);

      j++;
    }

    Point from = p - B;
    Point to = B - p;

    if (!above(p)) swap(from, to);

    const int a = lower_bound(ord_b.begin(), ord_b.end(), from, cmp_by_b) - ord_b.begin();
    const int b = lower_bound(ord_b.begin(), ord_b.end(), to, cmp_by_b) - ord_b.begin();

    total += sum(a, b - 1);
  }

  return total;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int N, M, Q;

  while (cin >> N >> M) {
    vector<vector<Point>> tribe_points(M + 1);
    vector<vector<Point>> order_by_b(M + 1);

    for (int i = 0; i < N; i++) {
      Point p;
      int tribe;
      cin >> p.x >> p.y >> tribe;
      tribe_points[tribe].push_back(p);
    }

    cin >> A.x >> A.y;
    cin >> B.x >> B.y;
    cin >> Q;
    B = B - A;

    for (int m = 0; m <= M; m++) {
      auto& points = tribe_points[m];
      for (auto& p : points) p = p - A;
      for (auto& p : points) p = p - B;
      sort(points.begin(), points.end(), cmp_by_b);
      for (int i = 0; i < (int)points.size(); i++) points[i].idx = i;
      auto& b = order_by_b[m];
      b = points;
      for (auto& p : points) p = p + B;
      sort(points.begin(), points.end());
    }

    while (Q--) {
      int i, j;
      cin >> i >> j;
      cout << query(tribe_points[i], tribe_points[j], order_by_b[j]) << '\n';
    }
  }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...