求最大最小凸包上三角形面积,可以考虑以y轴负半轴为极轴,进行排序,排序之后从小到大遍历所有二元组的边,此时直接对x坐标排序,接近的点一定是高最小的点,之后记得swap一下,因为画图可知此时两边的顺序倒了过来
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
using _T = LL;
constexpr _T eps = 0;
constexpr long double PI = 3.1415926535897932384l;
template <typename T>
struct point
{
T x, y;
point() {}
point(T x, T y) : x(x), y(y) {}
bool operator==(const point &a) const { return (abs(x - a.x) <= eps && abs(y - a.y) <= eps); }
bool operator<(const point &a) const { if (abs(x - a.x) <= eps) return y < a.y - eps; return x < a.x - eps; }
bool operator>(const point &a) const { return !(*this < a || *this == a); }
point operator+(const point &a) const { return {x + a.x, y + a.y}; }
point operator-(const point &a) const { return {x - a.x, y - a.y}; }
point operator-() const { return {-x, -y}; }
point operator*(const T k) const { return {k * x, k * y}; }
point operator/(const T k) const { return {x / k, y / k}; }
T operator*(const point &a) const { return x * a.x + y * a.y; } // 点乘 Dot
T operator^(const point &a) const { return x * a.y - y * a.x; } // 叉乘 Cross
// 1:左 -1:右 0:线上
// auto的原理就是根据后面的值,来自己推测前面的类型是什么。
// return *this返回当前对象,return this返回当前对象的地址(指向当前对象的指针)
int toleft(const point &a) const { const auto t = (*this) ^ a; return (t > eps) - (t < -eps); }
T len2() const { return (*this) * (*this); }
T dis2(const point &a) const { return (a - (*this)).len2(); }
double len() const { return sqrt(len2()); }
double dis(const point &a) const { return sqrt(dis2(a)); }
// 夹角
double ang(const point &a) const { return acos(max(-1.0, min(1.0, ((*this) * a) / (len() * a.len())))); }
// 逆时针旋转rad
point rot(const double rad) const { return {x * cos(rad) - y * sin(rad), x * sin(rad) + y * cos(rad)}; }
point rot(const double cosr, const double sinr) const { return {x * cosr - y * sinr, x * sinr + y * cosr}; }
};
using Point = point<_T>;
typedef Point Vector;
bool argcmp(const Point &a, const Point &b)
{
auto quad = [](const Point &a)
{
if (a.y < -eps) return 1;
if (a.y > eps) return 4;
if (a.x < -eps) return 5;
if (a.x > eps) return 3;
return 2;
};
int qa = quad(a), qb = quad(b);
if (qa != qb) return qa < qb;
auto t = a ^ b;
//if (abs(t) <= eps) return a * a < b * b - eps;
return t > eps;
}
pair<_T, _T> minmax_triangle(const vector<Point> &vec)
{
if (vec.size() <= 2) return {0, 0};
vector<pair<int, int>> evt;
evt.reserve(vec.size() * vec.size());
const _T t = abs((vec[0] - vec[1]) ^ (vec[0] - vec[2]));
_T maxans = t, minans = t;
for (size_t i = 0; i < vec.size(); i ++ )
{
for (size_t j = 0; j < vec.size(); j ++ )
{
if (i == j || vec[i] == vec[j]) continue;
evt.push_back({i, j});
}
}
sort(evt.begin(), evt.end(), [&](const pair<int, int> &u, const pair<int, int> &v)
{
const Point du = vec[u.second] - vec[u.first], dv = vec[v.second] - vec[v.first];
return argcmp({du.y,-du.x}, {dv.y,-dv.x});
});
vector<size_t> vx(vec.size()), pos(vec.size());
for (size_t i = 0; i < vec.size(); i ++ ) vx[i] = i;
sort(vx.begin(), vx.end(), [&](int x, int y) { return vec[x] < vec[y]; });
for (size_t i = 0; i < vx.size(); i++) pos[vx[i]] = i;
for (auto [u, v] : evt)
{
//printf("%d %d-\n",u,v);
size_t i = pos[u], j = pos[v];
if (i > j) swap(u, v), swap(i, j);
const Point vecu = vec[u], vecv = vec[v];
if (i > 0) minans = min(minans, abs((vec[vx[i - 1]] - vecu) ^ (vec[vx[i - 1]] - vecv)));
if (j < vx.size() - 1) minans = min(minans, abs((vec[vx[j + 1]] - vecu) ^ (vec[vx[j + 1]] - vecv)));
maxans = max({maxans, abs((vec[vx[0]] - vecu) ^ (vec[vx[0]] - vecv)), abs((vec[vx.back()] - vecu) ^ (vec[vx.back()] - vecv))});
swap(vx[i], vx[j]);
pos[u] = j;
pos[v] = i;
}
return {minans, maxans};
}
signed main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n;
cin >> n;
vector<int> a(n), b(n);
vector<Point> vec(n);
for(int i = 0; i < n; i ++ ) cin >> a[i];
for(int i = 0; i < n; i ++ ) cin >> b[i];
for(int i = 0; i < n; i ++ ) vec[i] = {a[i], b[i]};
auto ans = minmax_triangle(vec);
cout << ans.first << '\n' << ans.second << '\n';
return 0;
}