Submission #955863

# Submission time Handle Problem Language Result Execution time Memory
955863 2024-03-31T15:43:54 Z chrisvilches Dragon 2 (JOI17_dragon2) C++14
0 / 100
55 ms 4820 KB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

ll Bx, By;

map<pair<int, int>, int> ans;
set<pair<int, int>> queries;

struct Point {
  ll x, y;
  int idx;
  int tribe;
  Point operator-(const Point p) const { return {x - p.x, y - p.y, idx, tribe}; }
  Point operator+(const Point p) const { return {x + p.x, y + p.y, idx, tribe}; }
  ll cross(const Point p) const { return x * p.y - y * p.x; }
  bool operator<(const Point p) const { return to_upper().cross(p.to_upper()) > 0; }
  Point to_upper() const { return above() ? *this : negate(); }
  bool above() const {
    // TODO: Improve this
    const Point B{Bx, By, -1, -1};
    return B.cross(*this) > 0;
  }
  ll operator*(const Point p) const { return x * p.x + y * p.y; }
  bool deg0(const Point p) const { return cross(p) == 0 && *this * p >= 0; }
  bool deg180(const Point p) const { return cross(p) == 0 && *this * p < 0; }
  Point negate() const { return {-x, -y, idx, tribe}; }
};

template <class T, unsigned int N>
struct BIT {
  void clear(const int n) { fill(bit, bit + n, 0); }

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

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

 private:
  T bit[N];

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

unordered_map<int, vector<Point>> order_by_b;

bool cmp_by_b(Point p, Point q) {
  p.x -= Bx;
  q.x -= Bx;
  p.y -= By;
  q.y -= By;
  const bool a1 = p.above();
  const bool a2 = q.above();
  if (a1 != a2) return a1;
  return p.cross(q) > 0;
}

BIT<int, 30'001> active;

void handle_query(const vector<Point>& points1, const vector<Point>& points2,
                  const vector<Point>& ord_b, const int attacked_tribe_idx,
                  const Point B) {
  if (points1.empty() || points2.empty()) return;

  active.clear(points2.size());

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

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

      if (q.to_upper().cross(p.to_upper()) < 0) break;

      if (q.above()) {
        active.add(q.idx, 1);
      } else {
        active.add(q.idx, -1);
      }
      j++;
    }

    Point from_point = p;
    Point to_point = B + (p - B).negate();

    if (!p.above()) swap(from_point, to_point);

    const auto it1 = lower_bound(ord_b.begin(), ord_b.end(), from_point, cmp_by_b);
    const auto it2 = lower_bound(ord_b.begin(), ord_b.end(), to_point, cmp_by_b);

    const int from = it1 - ord_b.begin();
    const int to = it2 - ord_b.begin();

    ans[{p.tribe, attacked_tribe_idx}] += active.sum(from, to - 1);
  }
}

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

  while (cin >> N >> M) {
    ans.clear();
    vector<Point> points;
    unordered_map<int, vector<Point>> tribe_points;
    for (int i = 0; i < N; i++) {
      Point p;
      cin >> p.x >> p.y >> p.tribe;
      tribe_points[p.tribe].push_back(p);
    }

    Point A;
    cin >> A.x >> A.y;
    cin >> Bx >> By;
    cin >> Q;

    Bx -= A.x;
    By -= A.y;

    for (auto& [_, points] : tribe_points) {
      for (auto& p : points) p = p - A;
    }

    for (auto& [tribe_idx, points] : tribe_points) {
      sort(points.begin(), points.end(), cmp_by_b);
      for (int i = 0; i < (int)points.size(); i++) points[i].idx = i;
      order_by_b[tribe_idx] = points;
    }

    vector<Point> all;

    for (auto& [_, points] : tribe_points) {
      for (const auto p : points) all.emplace_back(p);
    }

    for (auto& [_, points] : tribe_points) {
      sort(points.begin(), points.end());
    }

    sort(all.begin(), all.end());

    const Point B{Bx, By, -1, -1};

    queries.clear();

    map<int, int> attacked;

    while (Q--) {
      int i, j;
      cin >> i >> j;
      attacked[j]++;
      queries.emplace(i, j);
    }

    set<int> solved_attacked;

    const int sqrtn = sqrt(N);

    for (int i = 0; i < N; i++) {
      if (attacked[i] > sqrtn) {
        handle_query(all, tribe_points[i], order_by_b[i], i, B);
        solved_attacked.emplace(i);
      }
    }

    for (const auto& [i, j] : queries) {
      if (solved_attacked.count(j)) continue;
      handle_query(tribe_points[i], tribe_points[j], order_by_b[j], j, B);
    }

    for (const auto& [i, j] : queries) {
      cout << ans[{i, j}] << '\n';
    }
  }
}

Compilation message

dragon2.cpp: In function 'int main()':
dragon2.cpp:131:16: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  131 |     for (auto& [_, points] : tribe_points) {
      |                ^
dragon2.cpp:135:16: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  135 |     for (auto& [tribe_idx, points] : tribe_points) {
      |                ^
dragon2.cpp:143:16: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  143 |     for (auto& [_, points] : tribe_points) {
      |                ^
dragon2.cpp:147:16: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  147 |     for (auto& [_, points] : tribe_points) {
      |                ^
dragon2.cpp:177:22: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  177 |     for (const auto& [i, j] : queries) {
      |                      ^
dragon2.cpp:182:22: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  182 |     for (const auto& [i, j] : queries) {
      |                      ^
# Verdict Execution time Memory Grader output
1 Correct 3 ms 860 KB Output is correct
2 Incorrect 5 ms 860 KB Output isn't correct
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 24 ms 4032 KB Output is correct
2 Incorrect 55 ms 4820 KB Output isn't correct
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 3 ms 860 KB Output is correct
2 Incorrect 5 ms 860 KB Output isn't correct
3 Halted 0 ms 0 KB -