Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- struct Point {
- long long x, y;
- };
- Point operator-(Point a, Point b) {
- return {a.x - b.x, a.y - b.y};
- }
- long long cross_product(Point p1, Point p2, Point p3) {
- return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
- }
- vector<Point> convex_hull(vector<Point> points) {
- int n = points.size();
- if (n <= 2) return points;
- sort(points.begin(), points.end(), [](Point a, Point b) {
- if (a.x != b.x) return a.x < b.x;
- return a.y < b.y;
- });
- vector<Point> lower_hull, upper_hull;
- for (const auto& p : points) {
- while (lower_hull.size() >= 2 && cross_product(lower_hull[lower_hull.size()-2], lower_hull.back(), p) <= 0) {
- lower_hull.pop_back();
- }
- lower_hull.push_back(p);
- }
- for (int i = n - 1; i >= 0; --i) {
- const auto& p = points[i];
- while (upper_hull.size() >= 2 && cross_product(upper_hull[upper_hull.size()-2], upper_hull.back(), p) <= 0) {
- upper_hull.pop_back();
- }
- upper_hull.push_back(p);
- }
- lower_hull.pop_back();
- upper_hull.pop_back();
- lower_hull.insert(lower_hull.end(), upper_hull.begin(), upper_hull.end());
- return lower_hull;
- }
- bool is_inside_hull(const vector<Point>& hull, Point p) {
- int h = hull.size();
- if (h < 3) return false;
- if (cross_product(hull[0], hull[1], p) < 0 || cross_product(hull[0], hull[h - 1], p) > 0) {
- return false;
- }
- int low = 1, high = h - 2;
- int target_idx = -1;
- while(low <= high) {
- int mid = low + (high - low) / 2;
- if (cross_product(hull[0], hull[mid], p) >= 0) {
- target_idx = mid;
- low = mid + 1;
- } else {
- high = mid - 1;
- }
- }
- if (target_idx == -1) return false;
- return cross_product(hull[target_idx], hull[target_idx + 1], p) >= 0;
- }
- int calculate_score(vector<Point>& team_stones, vector<Point>& opponent_stones) {
- if (team_stones.size() < 3) {
- return 0;
- }
- vector<Point> hull = convex_hull(team_stones);
- if (hull.size() < 3) {
- sort(team_stones.begin(), team_stones.end(), [](Point a, Point b) {
- if (a.x != b.x) return a.x < b.x;
- return a.y < b.y;
- });
- Point p1 = team_stones.front();
- Point p2 = team_stones.back();
- int score = 0;
- for (const auto& stone : opponent_stones) {
- if (cross_product(p1, p2, stone) == 0) {
- if (stone.x >= p1.x && stone.x <= p2.x &&
- stone.y >= min(p1.y, p2.y) && stone.y <= max(p1.y, p2.y)) {
- score++;
- }
- }
- }
- return score;
- }
- int score = 0;
- for (const auto& opponent_stone : opponent_stones) {
- if (is_inside_hull(hull, opponent_stone)) {
- score++;
- }
- }
- return score;
- }
- int main() {
- ios_base::sync_with_stdio(false);
- cin.tie(NULL);
- freopen("curling.in", "r", stdin);
- freopen("curling.out", "w", stdout);
- int n;
- cin >> n;
- vector<Point> team_a(n), team_b(n);
- for (int i = 0; i < n; ++i) cin >> team_a[i].x >> team_a[i].y;
- for (int i = 0; i < n; ++i) cin >> team_b[i].x >> team_b[i].y;
- int score_a = calculate_score(team_a, team_b);
- int score_b = calculate_score(team_b, team_a);
- cout << score_a << " " << score_b << endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement