Cod sursa(job #3314232)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 9 octombrie 2025 00:27:47
Problema Aria Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.71 kb
#include <array>
#include <cmath>
#include <functional>
#include <iostream>
#include <type_traits>
#include <utility>

template<typename T, std::size_t N = 2>
  requires std::is_floating_point_v<T>
class Point {
  std::array<T, N> x_{};

  // Apply callable coordinate-wise to *this and optional others.
  template<typename Predicate, typename... Points>
  constexpr Point convolute(Predicate &&predicate, Points const &... that) const
    noexcept(std::is_nothrow_invocable_v<Predicate, T, decltype(that[0])...>) {
    Point out{};
    for (std::size_t i = 0; i < N; ++i)
      out[i] = std::invoke(predicate, (*this)[i], that[i]...);
    return out;
  }

public:
public:
  // default constructor: zero initialize
  constexpr Point() noexcept = default;

  // Variadic constructor for exactly N arguments.
  template<typename... Ts>
    requires (sizeof...(Ts) == N) &&
             (std::conjunction_v<std::is_convertible<Ts, T>...>) &&
             (sizeof...(Ts) > 0)
  constexpr explicit Point(Ts&&... args) noexcept
    : x_{ static_cast<T>(std::forward<Ts>(args))... } {}

  // element access
  [[nodiscard]] constexpr T &operator[](std::size_t i) noexcept { return x_[i]; }
  [[nodiscard]] constexpr T const &operator[](std::size_t i) const noexcept { return x_[i]; }

  // ---------- arithmetic ----------
  [[nodiscard]] constexpr Point operator-() const noexcept {
    return convolute(std::negate<>{});
  }

  [[nodiscard]] constexpr Point operator+() const noexcept { return *this; }

  [[nodiscard]] constexpr Point operator+(Point const &that) const noexcept {
    return convolute(std::plus<>{}, that);
  }

  constexpr Point &operator+=(Point const &that) noexcept {
    *this = *this + that;
    return *this;
  }

  [[nodiscard]] constexpr Point operator-(Point const &that) const noexcept {
    return convolute(std::minus<>{}, that);
  }

  constexpr Point &operator-=(Point const &that) noexcept {
    *this = *this - that;
    return *this;
  }

  [[nodiscard]] constexpr Point operator*(T k) const noexcept {
    return convolute([k](T a) noexcept { return a * k; });
  }

  constexpr Point &operator*=(T k) noexcept {
    *this = *this * k;
    return *this;
  }

  [[nodiscard]] constexpr Point operator/(T k) const noexcept {
    return convolute([k](T a) noexcept { return a / k; });
  }

  constexpr Point &operator/=(T k) noexcept {
    *this = *this / k;
    return *this;
  }

  [[nodiscard]] T cross(Point const &that) const noexcept
    requires (N == 2) {
    return (*this)[0] * that[1] - (*this)[1] * that[0];
  }

  friend constexpr Point operator*(T k, Point const &p) noexcept { return p * k; }

  // element-wise power
  [[nodiscard]] constexpr Point operator^(std::size_t exp) const noexcept {
    return convolute([exp](T a) noexcept { return std::pow(a, static_cast<T>(exp)); });
  }

  constexpr Point &operator^=(std::size_t exp) noexcept {
    *this = *this ^ exp;
    return *this;
  }

  // ---------- utilities ----------
  [[nodiscard]] constexpr Point sqrp() const noexcept {
    Point out{};
    for (std::size_t i = 0; i < N; ++i)
      out[i] = x_[i] * x_[i];
    return out;
  }

  // Euclidean distance
  [[nodiscard]] T dist(Point const &that) const noexcept {
    T sum{};
    for (std::size_t i = 0; i < N; ++i) {
      T d = x_[i] - that.x_[i];
      sum += d * d;
    }
    return std::sqrt(sum);
  }

  // coordinate-wise absolute value
  [[nodiscard]] constexpr Point abs() const noexcept {
    return convolute([](T a) noexcept { return std::fabs(a); });
  }

  // ---------- I/O ----------
  friend std::istream &operator>>(std::istream &is, Point &p) {
    for (auto &d: p.x_) is >> d;
    return is;
  }

  friend std::ostream &operator<<(std::ostream &os, Point const &p) {
    for (auto const &d: p.x_) os << d << ' ';
    return os;
  }
};

template<typename T, std::size_t N = 2>
  requires std::is_floating_point_v<T>
class Convex {
  std::vector<Point<T, N> > p_;

public:
  // ---- Constructors ----
  Convex() = default;

  explicit Convex(std::vector<Point<T, N> > pts) : p_(std::move(pts)) {
  }

  template<typename... Ps>
    requires (sizeof...(Ps) >= 3) &&
             (std::conjunction_v<std::is_convertible<Ps, Point<T, N> >...>)
  explicit Convex(Ps &&... pts) : p_{std::forward<Ps>(pts)...} {
  }

  // ---- Basic access ----
  [[nodiscard]] std::size_t size() const noexcept { return p_.size(); }

  [[nodiscard]] Point<T, N> const &operator[](std::size_t i) const noexcept { return p_[i]; }
  [[nodiscard]] Point<T, N> &operator[](std::size_t i) noexcept { return p_[i]; }

  // ---- Centroid (geometric average) ----
  [[nodiscard]] Point<T, N> inner() const noexcept {
    Point<T, N> centroid{};
    if (p_.empty()) return centroid;
    for (auto const &pt: p_) centroid += pt;
    centroid /= static_cast<T>(p_.size());
    return centroid;
  }

  // ---- Area (2D only) ----
  [[nodiscard]] T area() const noexcept
    requires (N == 2) {
    if (p_.size() < 3) return T{};
    T a{};
    for (std::size_t i = 0; i < p_.size(); ++i) {
      a += p_[i].cross(p_[(i + 1) % p_.size()]);
    }
    return std::fabs(a) / 2;
  }

  // ---- I/O ----
  friend std::istream &operator>>(std::istream &is, Convex &c) {
    std::size_t n;
    if (!(is >> n)) return is;
    c.p_.resize(n);
    for (auto &pt: c.p_) is >> pt;
    return is;
  }

  friend std::ostream &operator<<(std::ostream &os, Convex const &c) {
    os << c.p_.size() << '\n';
    for (auto const &pt: c.p_) os << pt << '\n';
    return os;
  }
};

#include<bits/stdc++.h>

using namespace std;

int main() {
#ifndef LOCAL
  freopen("aria.in", "r", stdin);
  freopen("aria.out", "w", stdout);
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
#endif
  Convex<long double> shape{};
  cin >> shape;
  cout << fixed << setprecision(6) << static_cast<double>(shape.area()) << '\n';
  return 0;
}