Problem:
Problem H:
Magic Walls
You are a magician and have a large farm to grow magical fruits.
One day, you saw a horde of monsters, approaching your farm. They would ruin your magical farm once they reached your farm. Unfortunately, you are not strong enough to fight against those monsters. To protect your farm against them, you decided to build magic walls around your land.
You have four magic orbs to build the walls, namely, the orbs of Aquamarine (A), Bloodstone (B), Citrine (C) and Diamond (D). When you place them correctly and then cast a spell, there will be magic walls between the orbs A and B, between B and C, between C and D, and between D and A. The walls are built on the line segments connecting two orbs, and form a quadrangle as a whole. As the monsters cannot cross the magic walls, the inside of the magic walls is protected.
Nonetheless, you can protect only a part of your land, since there are a couple of restrictions on building the magic walls. There are
N
hills in your farm, where the orbs can receive rich power of magic. Each orb should be set on the top of one of the hills. Also, to avoid interference between the orbs, you may not place two or more orbs at the same hill.
Now, you want to maximize the area protected by the magic walls. Please figure it out.
Input
The input begins with an integer
N
(4 ≤
N
≤ 1500), the number of the hills. Then
N
line follow. Each of them has two integers
x
(0 ≤
x
≤ 50000) and
y
(0 ≤
y
≤ 50000), the
x
- and
y
-coordinates of the location of a hill.
It is guaranteed that no two hills have the same location and that no three hills lie on a single line.
Output
Output the maximum area you can protect. The output value should be printed with one digit after the decimal point, and should be exact.
Sample Input 1
5
2 0
0 1
1 3
4 2
3 4
Output for the Sample Input 1
7.5
Sample Input 2
4
0 0
0 3
1 1
3 0
Output for the Sample Input 2
3.0

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1505;

struct Point {
    LL x, y;
    Point(LL _x = 0, LL _y = 0): x(_x), y(_y) {}
    Point operator + (const Point &rhs) const {
        return Point(x + rhs.x, y + rhs.y);
    }
    Point operator - (const Point &rhs) const {
        return Point(x - rhs.x, y - rhs.y);
    }
    LL operator * (const Point &rhs) const {
        return x * rhs.x + y * rhs.y;
    }
    LL operator ^ (const Point &rhs) const {
        return x * rhs.y - y * rhs.x;
    }
    bool operator == (const Point &rhs) const {
        return x == rhs.x && y == rhs.y;
    }
};
typedef vector<Point> Polygon;

inline LL Area(Point a, Point b, Point c) {
    return llabs((b - a) ^ (c - a));
}

Polygon ConvexHull(Polygon a) {
    int n = a.size();
    sort(a.begin(), a.end(), [](Point a, Point b) {
        return make_pair(a.y, a.x) < make_pair(b.y, b.x);
    });
    Polygon ret(n * 2);
    int top = 0;
    for (int i = 0; i < n; ++i) {
        while (top > 1 && ((a[i] - ret[top - 2]) ^ (ret[top - 1] - ret[top - 2])) > 0) {
            --top;
        }
        ret[top++] = a[i];
    }
    for (int i = n - 2, t = top; i >= 0; --i) {
        while (top > t && ((a[i] - ret[top - 2]) ^ (ret[top - 1] - ret[top - 2])) > 0) {
            --top;
        }
        ret[top++] = a[i];
    }
    ret.resize(top - 1);
    return ret;
}

LL siz[N][N];

void solve() {
    int n;
    scanf("%d", &n);
    Polygon p(n);
    for (int i = 0; i < n; ++i) {
        scanf("%lld %lld", &p[i].x, &p[i].y);
    }
    Polygon h = ConvexHull(p);
    int m = h.size();
    LL ans = 0;
    if (m == 3) {
        LL sub = 1e18;
        for (int i = 0; i < n; ++i) {
            if (p[i] == h[0] || p[i] == h[1] || p[i] == h[2]) continue;
            sub = min(sub, Area(p[i], h[0], h[1]));
            sub = min(sub, Area(p[i], h[1], h[2]));
            sub = min(sub, Area(p[i], h[2], h[0]));
        }
        ans = Area(h[0], h[1], h[2]) - sub;
    } else {
        h.resize(m * 2);
        for (int i = 0; i < m; ++i) {
            h[m + i] = h[i];
        }
        for (int i = 0; i < m; ++i) {
            for (int j = i + 2, k = i + 1; j < i + m - 1; ++j) {
                while (k + 1 < j && Area(h[i], h[k], h[j]) < Area(h[i], h[k + 1], h[j])) {
                    ++k;
                }
                siz[i][j % m] = Area(h[i], h[k], h[j]);
            }
        }
        for (int i = 0; i < m; ++i) {
            for (int j = i + 2, k = i + 1; j < i + m - 1; ++j) {
                ans = max(ans, siz[i][j % m] + siz[j % m][i]);
            }
        }
    }
    printf("%lld.%d\n", ans / 2, (ans & 1)? 5 : 0);
}

int main() {
    solve();
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 21176
final_rank: 8

code_snippet: #include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
#include<tuple>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
typedef complex<D> P;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){ll i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T>vector<T> & cset(vector<T> &A,T e=T()){for(auto &I:A){I=e;} return A;}

namespace Geometry{
    typedef long double D;
    typedef complex<long double> P;
    typedef pair<P,D> C;
    
    const D EPS=1e-9;
    const D PI=asin(1)*2;
    const D INF=1e18;
    
    static bool comp(const P &p1,const P &p2){
        if(p1.real()==p2.real()){return p1.imag()<p2.imag();}
        return p1.real()<p2.real();
    }
    
    static bool comp_y(const P &p1,const P &p2){
        if(p1.imag()==p2.imag()){return p1.real()<p2.real();}
        return p1.imag()<p2.imag();
    }
    
    static bool eqls(const P &p1,const P &p2){return abs(p1-p2)<EPS;}
    
    D dot(P p1,P p2){return p1.real()*p2.real()+p1.imag()*p2.imag();}
    
    D cross(P p1,P p2){return p1.real()*p2.imag()-p1.imag()*p2.real();}
    
    P project(P vec,P x){return vec*(x/vec).real();}
    
    P project(P p1,P p2,P x){return p1+project(p2-p1,x-p1);}
    
    P reflect(P vec,P x){return vec*conj(x/vec);}
    
    P reflect(P p1,P p2,P x){return p1+reflect(p2-p1,x-p1);}
    
    bool intersectSL(P p1,P p2,P vec){
        vec/=abs(vec); p1/=vec; p2/=vec;
        return (p1.imag()<EPS && p2.imag()>-EPS) || (p1.imag()>-EPS && p2.imag()<EPS);
    }
    
    bool intersectSL(P p1,P p2,P p3,P p4){return intersectSL(p1-p4,p2-p4,p3-p4);}
    
    bool intersectSS(P p1,P p2,P p3,P p4){
        if(dot(p2-p1,p3-p1)<-EPS && dot(p2-p1,p4-p1)<-EPS){return false;}
        if(dot(p1-p2,p3-p2)<-EPS && dot(p1-p2,p4-p2)<-EPS){return false;}
        return intersectSL(p1,p2,p3,p4) && intersectSL(p3,p4,p1,p2);
    }
    
    D distLP(P vec,P x){return abs((x/vec).imag())*abs(vec);}
    
    D distLP(P p1,P p2,P x){return distLP(p2-p1,x-p1);}
    
    D distSP(P p1,P p2,P x){
        if(dot(p2-p1,x-p1)<-EPS){return abs(x-p1);}
        if(dot(p1-p2,x-p2)<-EPS){return abs(x-p2);}
        return distLP(p1,p2,x);
    }
    
    D distSS(P p1,P p2,P p3,P p4){
        if(intersectSS(p1,p2,p3,p4)){return 0.0;}
        return min({distSP(p1,p2,p3),distSP(p1,p2,p4),
            distSP(p3,p4,p1),distSP(p3,p4,p2)});
    }
    
    P crosspointLL(P p1,P p2,P vec){
        if(abs(cross(p2-p1,vec))<EPS){return vec;}
        return vec*cross(p2-p1,p2)/cross(p2-p1,vec);
    }
    
    P crosspointLL(P p1,P p2,P p3,P p4){
        return p4+crosspointLL(p1-p4,p2-p4,p3-p4);
    }
    
    P crosspointSS(P p1,P p2,P p3,P p4){
        if(distSP(p1,p2,p3)<EPS){return p3;}
        if(distSP(p1,p2,p4)<EPS){return p4;}
        return crosspointLL(p1,p2,p3,p4);
    }
    
    bool intersectShL(P p1,P p2,P vec){
        vec/=abs(vec);
        return intersectSL(p1,p2,vec) &&
        crosspointLL(p1/vec,p2/vec,vec/vec).real()>-EPS;
    }
    
    bool intersectShL(P p1,P p2,P p3,P p4){
        return intersectShL(p1-p3,p2-p3,p4-p3);
    }
    
    //1::in,0::on edge,-1::out
    int contain(const vector<P> &poly,const P &p){
        vector<P> A={{65537,96847},{-24061,6701},{56369,-86509},{-93763,-78049},{56957,10007}};
        int s=A.size();
        vector<bool> cnt(s,false);
        for(int i=0;i<(int)poly.size();i++){
            int k=(i+1)%poly.size();
            if(distSP(poly[i],poly[k],p)<EPS){return 0;}
            for(int j=0;j<s;j++){
                if(intersectShL(poly[i],poly[k],p,p+A[j])){cnt[j]=!cnt[j];}
            }
        }
        int in=0;
        for(int j=0;j<s;j++){if(cnt[j]){in++;}}
        return in>s/2?1:-1;
    }
    
    vector<P> convexcut(const vector<P> &poly,P p1,P p2){
        vector<P> ret;
        for(int i=0;i<(int)poly.size();i++){
            int j=(i+1)%poly.size();
            if(cross(p2-p1,poly[i]-p1)>-EPS){ret.push_back(poly[i]);}
            if(intersectSL(poly[i],poly[j],p1,p2) &&
               distLP(p1,p2,poly[i])>EPS && distLP(p1,p2,poly[j])>EPS){
                ret.push_back(crosspointLL(poly[i],poly[j],p1,p2));
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly){
        D ans=0;
        for(int i=2;i<(int)poly.size();i++){
            ans+=cross(poly[i-1]-poly[0],poly[i]-poly[0]);
        }
        return abs(ans)/2;
    }
    
    vector<P> convexhull(vector<P> pts){
        vector<P> ret;
        sort(pts.begin(),pts.end(),comp);
        auto fnc=[&](){
            for(auto &I:pts){
                if(!ret.empty() && I==ret.back()){continue;}
                while(ret.size()>=2 && cross(ret.back()-ret[ret.size()-2],I-ret.back())<-EPS){
                    ret.pop_back();
                }
                ret.push_back(I);
            }
        };
        fnc();
        reverse(pts.begin(),pts.end());
        fnc();
        if(ret[0]==ret.back()){ret.pop_back();}
        return ret;
    }
    
    //4::seperate,3::circumscribe,2::intersect,1::inscribe,0::contain,-1::same
    int intersectCC(C c1,C c2){
        D d=abs(c1.F-c2.F),r=c1.S+c2.S,dif=abs(c2.S-c1.S);
        if(d<EPS && dif<EPS){return -1;}
        if(d-r>EPS){return 4;}
        if(d-r>-EPS){return 3;}
        if(d-dif>EPS){return 2;}
        if(d-dif>-EPS){return 1;}
        return 0;
    }
    
    vector<P> crosspointLC(P p1,P p2,C c){
        vector<P> ret;
        P pr=project(p1,p2,c.F);
        D d=distLP(p1,p2,c.F);
        if(d-c.S>EPS){return ret;}
        if(d-c.S>-EPS){ret.push_back(pr); return ret;}
        P vec=p2-p1; vec*=sqrt(c.S*c.S-d*d)/abs(vec);
        ret.push_back(pr-vec);
        ret.push_back(pr+vec);
        return ret;
    }
    
    vector<P> crosspointSC(P p1,P p2,C c){
        vector<P> ret;
        for(auto &I:crosspointLC(p1,p2,c)){
            if(distSP(p1,p2,I)<EPS){ret.push_back(I);}
        }
        return ret;
    }
    
    vector<P> crosspointCC(C c1,C c2){
        vector<P> ret;
        P vec=c2.F-c1.F;
        D base=(c1.S*c1.S+norm(vec)-c2.S*c2.S)/(2*abs(vec));
        D h=sqrt(c1.S*c1.S-base*base);
        vec/=abs(vec);
        ret.push_back(c1.F+vec*P(base,-h));
        ret.push_back(c1.F+vec*P(base,h));
        return ret;
    }
    
    vector<P> tangentCP(C c,P p){
        return crosspointCC(c,C(p,sqrt(norm(c.F-p)-c.S*c.S)));
    }
    
    vector<pair<P,P>> tangentCC(C c1,C c2){
        vector<pair<P,P>> ret;
        P d=c2.F-c1.F;
        for(D i:{-1,1}){
            D r=c1.S+c2.S*i;
            if(intersectCC(c1,c2)>i+1){
                for(P s:{-1i,1i}){
                    P p=r+s*sqrt(norm(d)-norm(r));
                    ret.push_back({c1.F+d*c1.S/norm(d)*p,c2.F-d*i*c2.S/norm(d)*p});
                }
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly,C c){
        D ret=0;
        for(int i=0;i<(int)poly.size();i++){
            P a=poly[i]-c.F,b=poly[(i+1)%poly.size()]-c.F;
            if(abs(a)<c.S+EPS && abs(b)<c.S+EPS){ret+=cross(a,b);}
            else{
                vector<P> A=crosspointSC(a,b,{0,c.S});
                if(A.empty()){ret+=c.S*c.S*arg(b/a);}
                else{
                    ret+=(abs(a)<c.S?cross(a,A[0]):c.S*c.S*arg(A[0]/a));
                    ret+=(abs(b)<c.S?cross(A.back(),b):c.S*c.S*arg(b/A.back()));
                    ret+=cross(A[0],A.back());
                }
            }
        }
        return abs(ret)/2;
    }
    
    //反時計回り
    D diameter(const vector<P> &poly){
        D ret=0;
        ll l=0,r=0,n=poly.size();
        if(n==2){return abs(poly[0]-poly[1]);}
        for(int i=0;i<n;i++){
            if(comp(poly[l],poly[i])){l=i;}
            if(comp(poly[i],poly[r])){r=i;}
        }
        ll sl=r,sr=l;
        while(sl!=l || sr!=r){
            ret=max(ret,abs(poly[r]-poly[l]));
            if(cross(poly[(l+1)%n]-poly[l],poly[(r+1)%n]-poly[r])<0){(++l)%=n;}
            else{(++r)%=n;}
        }
        return ret;
    }
    
    D closestpair(vector<P> pt){
        sort(pt.begin(),pt.end(),comp);
        D ret=INF;
        int N=pt.size();
        for(int i=1;i<N;i<<=1){
            for(int j=0;i+j<N;j+=i*2){
                int m=i+j;
                vector<P> R;
                D l=-INF,r=INF;
                for(int k=j;k<m;k++){l=max(l,pt[k].real());}
                for(int k=0;m+k<N && k<i;k++){r=min(r,pt[m+k].real());}
                for(int k=0;m+k<N && k<i;k++){
                    if(pt[m+k].real()-l<ret){R.push_back(pt[m+k]);}
                }
                int idx=0;
                for(int k=j;k<m;k++){
                    if(r-pt[k].real()>ret){continue;}
                    int M=R.size();
                    while(idx<M && pt[k].imag()-R[idx].imag()>ret){idx++;}
                    for(int s=idx;s<M && R[s].imag()-pt[k].imag()<ret;s++){
                        ret=min(ret,abs(R[s]-pt[k]));
                    }
                }
                auto ed=(j+i*2<N?pt.begin()+j+2*i:pt.end());
                inplace_merge(pt.begin()+j,pt.begin()+m,ed,comp_y);
            }
        }
        return ret;
    }
    
    P centerofgravity(const vector<P> &pt){
        P ret(0,0);
        D wt=0;
        for(int i=2;i<(int)pt.size();i++){
            D w2=cross(pt[i-1]-pt[0],pt[i]-pt[0]);
            P p=(pt[0]+pt[i-1]+pt[i])/(D)3;
            wt+=w2;
            ret+=p*w2;
        }
        return ret/wt;
    }
    
    void segment_arrangement(const vector<pair<P,P>> &L,vector<pair<int,int>> &seg,vector<P> &pt){
        int N=L.size();
        for(int i=0;i<N;i++){
            pt.push_back(L[i].F);
            pt.push_back(L[i].S);
            for(int j=i+1;j<N;j++){
                if(intersectSS(L[i].F,L[i].S,L[j].F,L[j].S)){
                    pt.push_back(crosspointSS(L[i].F,L[i].S,L[j].F,L[j].S));
                }
            }
        }
        auto le=[](P a,P b){return eqls(a,b)?false:comp(a,b);};
        sort(pt.begin(),pt.end(),le);
        pt.erase(unique(pt.begin(),pt.end(),eqls),pt.end());
        for(auto &I:L){
            vector<pair<D,int>> on;
            for(int j=0;j<(int)pt.size();j++){
                if(distSP(I.F,I.S,pt[j])<EPS){
                    on.emplace_back(abs(pt[j]-I.F),j);
                }
            }
            sort(on.begin(),on.end());
            for(int j=1;j<(int)on.size();j++){
                seg.emplace_back(on[j-1].S,on[j].S);
            }
        }
        sort(seg.begin(),seg.end());
        seg.erase(unique(seg.begin(),seg.end()),seg.end());
    }
    
    vector<P> convex_of_segments(const vector<pair<P,P>> &L){
        vector<pair<int,int>> seg;
        vector<P> pt;
        segment_arrangement(L,seg,pt);
        vector<vector<int>> edge(pt.size());
        for(auto &I:seg){
            edge[I.F].push_back(I.S);
            edge[I.S].push_back(I.F);
        }
        vector<P> ret;
        function<void(int,int)> dfs=[&](int v,int pre){
            if(pre!=-1 && v==0){return;}
            ret.push_back(pt[v]);
            vector<pair<D,int>> nx;
            for(auto &u:edge[v]){
                D a=arg((pt[u]-pt[v])/(pre==-1 || eqls(pt[v],pt[pre])?P(1):pt[v]-pt[pre]));
                if(abs(a+PI)<EPS){a=PI;}
                nx.emplace_back(a,u);
            }
            sort(nx.begin(),nx.end());
            dfs(nx[0].S,v);
        };
        dfs(0,-1);
        return ret;
    }
    
    istream & operator >> (istream &i,P &p){D x,y; i>>x>>y; p={x,y}; return i;}
    istream & operator >> (istream &i,C &p){D x,y; i>>x>>y>>p.S; p.F={x,y}; return i;}
};


using namespace Geometry;


int main(){
    ll n;
    cin>>n;
    vector<P> A(n);
    cin>>A;
    auto C=convexhull(A);
    D ans=0;
    if(C.size()==3){
        for(auto &I:A){
            bool same=false;
            for(auto &J:C){same|=(I==J);}
            if(same){continue;}
            for(int j=0;j<4;j++){
                vector<P> x(4);
                for(int k=0;k<4;k++){
                    if(j==k){x[k]=I;}
                    else if(j<k){x[k]=C[k-1];}
                    else{x[k]=C[k];}
                }
                ans=max(ans,area(x));
            }
        }
    }
    else{
        ll m=C.size();
        for(int i=0;i<m;i++){
            int l=(i+1)%m;
            int r=(i+3)%m;
            for(int j=(i+2)%m;(j+1)%m!=i;j=(j+1)%m){
                while((l+1)%m!=j && cross(C[j]-C[i],C[(l+1)%m]-C[l])<-EPS){l=(l+1)%m;}
                while((r+1)%m!=i && (r==j || cross(C[j]-C[i],C[(r+1)%m]-C[r])>EPS)){r=(r+1)%m;}
                ans=max(ans,area({C[i],C[l],C[j],C[r]}));
            }
        }
    }
    cout<<fixed<<setprecision(1)<<ans<<endl;
    
    
    return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 3448
final_rank: 2

code_snippet: #include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
#include<tuple>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
typedef complex<D> P;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){ll i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T>vector<T> & cset(vector<T> &A,T e=T()){for(auto &I:A){I=e;} return A;}

namespace Geometry{
    typedef long double D;
    typedef complex<long double> P;
    typedef pair<P,D> C;
    
    const D EPS=1e-9;
    const D PI=asin(1)*2;
    const D INF=1e18;
    
    static bool comp(const P &p1,const P &p2){
        if(p1.real()==p2.real()){return p1.imag()<p2.imag();}
        return p1.real()<p2.real();
    }
    
    static bool comp_y(const P &p1,const P &p2){
        if(p1.imag()==p2.imag()){return p1.real()<p2.real();}
        return p1.imag()<p2.imag();
    }
    
    static bool eqls(const P &p1,const P &p2){return abs(p1-p2)<EPS;}
    
    D dot(P p1,P p2){return p1.real()*p2.real()+p1.imag()*p2.imag();}
    
    D cross(P p1,P p2){return p1.real()*p2.imag()-p1.imag()*p2.real();}
    
    P project(P vec,P x){return vec*(x/vec).real();}
    
    P project(P p1,P p2,P x){return p1+project(p2-p1,x-p1);}
    
    P reflect(P vec,P x){return vec*conj(x/vec);}
    
    P reflect(P p1,P p2,P x){return p1+reflect(p2-p1,x-p1);}
    
    bool intersectSL(P p1,P p2,P vec){
        vec/=abs(vec); p1/=vec; p2/=vec;
        return (p1.imag()<EPS && p2.imag()>-EPS) || (p1.imag()>-EPS && p2.imag()<EPS);
    }
    
    bool intersectSL(P p1,P p2,P p3,P p4){return intersectSL(p1-p4,p2-p4,p3-p4);}
    
    bool intersectSS(P p1,P p2,P p3,P p4){
        if(dot(p2-p1,p3-p1)<-EPS && dot(p2-p1,p4-p1)<-EPS){return false;}
        if(dot(p1-p2,p3-p2)<-EPS && dot(p1-p2,p4-p2)<-EPS){return false;}
        return intersectSL(p1,p2,p3,p4) && intersectSL(p3,p4,p1,p2);
    }
    
    D distLP(P vec,P x){return abs((x/vec).imag())*abs(vec);}
    
    D distLP(P p1,P p2,P x){return distLP(p2-p1,x-p1);}
    
    D distSP(P p1,P p2,P x){
        if(dot(p2-p1,x-p1)<-EPS){return abs(x-p1);}
        if(dot(p1-p2,x-p2)<-EPS){return abs(x-p2);}
        return distLP(p1,p2,x);
    }
    
    D distSS(P p1,P p2,P p3,P p4){
        if(intersectSS(p1,p2,p3,p4)){return 0.0;}
        return min({distSP(p1,p2,p3),distSP(p1,p2,p4),
            distSP(p3,p4,p1),distSP(p3,p4,p2)});
    }
    
    P crosspointLL(P p1,P p2,P vec){
        if(abs(cross(p2-p1,vec))<EPS){return vec;}
        return vec*cross(p2-p1,p2)/cross(p2-p1,vec);
    }
    
    P crosspointLL(P p1,P p2,P p3,P p4){
        return p4+crosspointLL(p1-p4,p2-p4,p3-p4);
    }
    
    P crosspointSS(P p1,P p2,P p3,P p4){
        if(distSP(p1,p2,p3)<EPS){return p3;}
        if(distSP(p1,p2,p4)<EPS){return p4;}
        return crosspointLL(p1,p2,p3,p4);
    }
    
    bool intersectShL(P p1,P p2,P vec){
        vec/=abs(vec);
        return intersectSL(p1,p2,vec) &&
        crosspointLL(p1/vec,p2/vec,vec/vec).real()>-EPS;
    }
    
    bool intersectShL(P p1,P p2,P p3,P p4){
        return intersectShL(p1-p3,p2-p3,p4-p3);
    }
    
    //1::in,0::on edge,-1::out
    int contain(const vector<P> &poly,const P &p){
        vector<P> A={{65537,96847},{-24061,6701},{56369,-86509},{-93763,-78049},{56957,10007}};
        int s=A.size();
        vector<bool> cnt(s,false);
        for(int i=0;i<(int)poly.size();i++){
            int k=(i+1)%poly.size();
            if(distSP(poly[i],poly[k],p)<EPS){return 0;}
            for(int j=0;j<s;j++){
                if(intersectShL(poly[i],poly[k],p,p+A[j])){cnt[j]=!cnt[j];}
            }
        }
        int in=0;
        for(int j=0;j<s;j++){if(cnt[j]){in++;}}
        return in>s/2?1:-1;
    }
    
    vector<P> convexcut(const vector<P> &poly,P p1,P p2){
        vector<P> ret;
        for(int i=0;i<(int)poly.size();i++){
            int j=(i+1)%poly.size();
            if(cross(p2-p1,poly[i]-p1)>-EPS){ret.push_back(poly[i]);}
            if(intersectSL(poly[i],poly[j],p1,p2) &&
               distLP(p1,p2,poly[i])>EPS && distLP(p1,p2,poly[j])>EPS){
                ret.push_back(crosspointLL(poly[i],poly[j],p1,p2));
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly){
        D ans=0;
        for(int i=2;i<(int)poly.size();i++){
            ans+=cross(poly[i-1]-poly[0],poly[i]-poly[0]);
        }
        return abs(ans)/2;
    }
    
    vector<P> convexhull(vector<P> pts){
        vector<P> ret;
        sort(pts.begin(),pts.end(),comp);
        auto fnc=[&](){
            for(auto &I:pts){
                if(!ret.empty() && I==ret.back()){continue;}
                while(ret.size()>=2 && cross(ret.back()-ret[ret.size()-2],I-ret.back())<-EPS){
                    ret.pop_back();
                }
                ret.push_back(I);
            }
        };
        fnc();
        reverse(pts.begin(),pts.end());
        fnc();
        if(ret[0]==ret.back()){ret.pop_back();}
        return ret;
    }
    
    //4::seperate,3::circumscribe,2::intersect,1::inscribe,0::contain,-1::same
    int intersectCC(C c1,C c2){
        D d=abs(c1.F-c2.F),r=c1.S+c2.S,dif=abs(c2.S-c1.S);
        if(d<EPS && dif<EPS){return -1;}
        if(d-r>EPS){return 4;}
        if(d-r>-EPS){return 3;}
        if(d-dif>EPS){return 2;}
        if(d-dif>-EPS){return 1;}
        return 0;
    }
    
    vector<P> crosspointLC(P p1,P p2,C c){
        vector<P> ret;
        P pr=project(p1,p2,c.F);
        D d=distLP(p1,p2,c.F);
        if(d-c.S>EPS){return ret;}
        if(d-c.S>-EPS){ret.push_back(pr); return ret;}
        P vec=p2-p1; vec*=sqrt(c.S*c.S-d*d)/abs(vec);
        ret.push_back(pr-vec);
        ret.push_back(pr+vec);
        return ret;
    }
    
    vector<P> crosspointSC(P p1,P p2,C c){
        vector<P> ret;
        for(auto &I:crosspointLC(p1,p2,c)){
            if(distSP(p1,p2,I)<EPS){ret.push_back(I);}
        }
        return ret;
    }
    
    vector<P> crosspointCC(C c1,C c2){
        vector<P> ret;
        P vec=c2.F-c1.F;
        D base=(c1.S*c1.S+norm(vec)-c2.S*c2.S)/(2*abs(vec));
        D h=sqrt(c1.S*c1.S-base*base);
        vec/=abs(vec);
        ret.push_back(c1.F+vec*P(base,-h));
        ret.push_back(c1.F+vec*P(base,h));
        return ret;
    }
    
    vector<P> tangentCP(C c,P p){
        return crosspointCC(c,C(p,sqrt(norm(c.F-p)-c.S*c.S)));
    }
    
    vector<pair<P,P>> tangentCC(C c1,C c2){
        vector<pair<P,P>> ret;
        P d=c2.F-c1.F;
        for(D i:{-1,1}){
            D r=c1.S+c2.S*i;
            if(intersectCC(c1,c2)>i+1){
                for(P s:{-1i,1i}){
                    P p=r+s*sqrt(norm(d)-norm(r));
                    ret.push_back({c1.F+d*c1.S/norm(d)*p,c2.F-d*i*c2.S/norm(d)*p});
                }
            }
        }
        return ret;
    }
    
    D area(const vector<P> &poly,C c){
        D ret=0;
        for(int i=0;i<(int)poly.size();i++){
            P a=poly[i]-c.F,b=poly[(i+1)%poly.size()]-c.F;
            if(abs(a)<c.S+EPS && abs(b)<c.S+EPS){ret+=cross(a,b);}
            else{
                vector<P> A=crosspointSC(a,b,{0,c.S});
                if(A.empty()){ret+=c.S*c.S*arg(b/a);}
                else{
                    ret+=(abs(a)<c.S?cross(a,A[0]):c.S*c.S*arg(A[0]/a));
                    ret+=(abs(b)<c.S?cross(A.back(),b):c.S*c.S*arg(b/A.back()));
                    ret+=cross(A[0],A.back());
                }
            }
        }
        return abs(ret)/2;
    }
    
    //反時計回り
    D diameter(const vector<P> &poly){
        D ret=0;
        ll l=0,r=0,n=poly.size();
        if(n==2){return abs(poly[0]-poly[1]);}
        for(int i=0;i<n;i++){
            if(comp(poly[l],poly[i])){l=i;}
            if(comp(poly[i],poly[r])){r=i;}
        }
        ll sl=r,sr=l;
        while(sl!=l || sr!=r){
            ret=max(ret,abs(poly[r]-poly[l]));
            if(cross(poly[(l+1)%n]-poly[l],poly[(r+1)%n]-poly[r])<0){(++l)%=n;}
            else{(++r)%=n;}
        }
        return ret;
    }
    
    D closestpair(vector<P> pt){
        sort(pt.begin(),pt.end(),comp);
        D ret=INF;
        int N=pt.size();
        for(int i=1;i<N;i<<=1){
            for(int j=0;i+j<N;j+=i*2){
                int m=i+j;
                vector<P> R;
                D l=-INF,r=INF;
                for(int k=j;k<m;k++){l=max(l,pt[k].real());}
                for(int k=0;m+k<N && k<i;k++){r=min(r,pt[m+k].real());}
                for(int k=0;m+k<N && k<i;k++){
                    if(pt[m+k].real()-l<ret){R.push_back(pt[m+k]);}
                }
                int idx=0;
                for(int k=j;k<m;k++){
                    if(r-pt[k].real()>ret){continue;}
                    int M=R.size();
                    while(idx<M && pt[k].imag()-R[idx].imag()>ret){idx++;}
                    for(int s=idx;s<M && R[s].imag()-pt[k].imag()<ret;s++){
                        ret=min(ret,abs(R[s]-pt[k]));
                    }
                }
                auto ed=(j+i*2<N?pt.begin()+j+2*i:pt.end());
                inplace_merge(pt.begin()+j,pt.begin()+m,ed,comp_y);
            }
        }
        return ret;
    }
    
    P centerofgravity(const vector<P> &pt){
        P ret(0,0);
        D wt=0;
        for(int i=2;i<(int)pt.size();i++){
            D w2=cross(pt[i-1]-pt[0],pt[i]-pt[0]);
            P p=(pt[0]+pt[i-1]+pt[i])/(D)3;
            wt+=w2;
            ret+=p*w2;
        }
        return ret/wt;
    }
    
    void segment_arrangement(const vector<pair<P,P>> &L,vector<pair<int,int>> &seg,vector<P> &pt){
        int N=L.size();
        for(int i=0;i<N;i++){
            pt.push_back(L[i].F);
            pt.push_back(L[i].S);
            for(int j=i+1;j<N;j++){
                if(intersectSS(L[i].F,L[i].S,L[j].F,L[j].S)){
                    pt.push_back(crosspointSS(L[i].F,L[i].S,L[j].F,L[j].S));
                }
            }
        }
        auto le=[](P a,P b){return eqls(a,b)?false:comp(a,b);};
        sort(pt.begin(),pt.end(),le);
        pt.erase(unique(pt.begin(),pt.end(),eqls),pt.end());
        for(auto &I:L){
            vector<pair<D,int>> on;
            for(int j=0;j<(int)pt.size();j++){
                if(distSP(I.F,I.S,pt[j])<EPS){
                    on.emplace_back(abs(pt[j]-I.F),j);
                }
            }
            sort(on.begin(),on.end());
            for(int j=1;j<(int)on.size();j++){
                seg.emplace_back(on[j-1].S,on[j].S);
            }
        }
        sort(seg.begin(),seg.end());
        seg.erase(unique(seg.begin(),seg.end()),seg.end());
    }
    
    vector<P> convex_of_segments(const vector<pair<P,P>> &L){
        vector<pair<int,int>> seg;
        vector<P> pt;
        segment_arrangement(L,seg,pt);
        vector<vector<int>> edge(pt.size());
        for(auto &I:seg){
            edge[I.F].push_back(I.S);
            edge[I.S].push_back(I.F);
        }
        vector<P> ret;
        function<void(int,int)> dfs=[&](int v,int pre){
            if(pre!=-1 && v==0){return;}
            ret.push_back(pt[v]);
            vector<pair<D,int>> nx;
            for(auto &u:edge[v]){
                D a=arg((pt[u]-pt[v])/(pre==-1 || eqls(pt[v],pt[pre])?P(1):pt[v]-pt[pre]));
                if(abs(a+PI)<EPS){a=PI;}
                nx.emplace_back(a,u);
            }
            sort(nx.begin(),nx.end());
            dfs(nx[0].S,v);
        };
        dfs(0,-1);
        return ret;
    }
    
    istream & operator >> (istream &i,P &p){D x,y; i>>x>>y; p={x,y}; return i;}
    istream & operator >> (istream &i,C &p){D x,y; i>>x>>y>>p.S; p.F={x,y}; return i;}
};


using namespace Geometry;


int main(){
    ll n;
    cin>>n;
    vector<P> A(n);
    cin>>A;
    auto C=convexhull(A);
    D ans=0;
    if(C.size()==3){
        for(auto &I:A){
            bool same=false;
            for(auto &J:C){same|=(I==J);}
            if(same){continue;}
            for(int j=0;j<4;j++){
                vector<P> x(4);
                for(int k=0;k<4;k++){
                    if(j==k){x[k]=I;}
                    else if(j<k){x[k]=C[k-1];}
                    else{x[k]=C[k];}
                }
                ans=max(ans,area(x));
            }
        }
    }
    else{
        ll m=C.size();
        for(int i=0;i<m;i++){
            int l=(i+1)%m;
            int r=(i+3)%m;
            for(int j=(i+2)%m;(j+1)%m!=i;j=(j+1)%m){
                while((l+1)%m!=j && cross(C[j]-C[i],C[(l+1)%m]-C[l])<EPS){l=(l+1)%m;}
                while((r+1)%m!=i && (r==j || cross(C[j]-C[i],C[(r+1)%m]-C[r])<EPS)){r=(r+1)%m;}
                ans=max(ans,area({C[i],C[l],C[j],C[r]}));
            }
        }
    }
    cout<<fixed<<setprecision(1)<<ans<<endl;
    
    
    return 0;
}
accuracy: 0.020833333333333332
time_ms: 280
memory_kb: 3292
final_rank: 13

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
using namespace std;
const double EPS = 1e-6;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b

}

double distanceLP(const L &l, const P &p) {
    return abs(cross(l[1]-l[0], p-l[0])) /abs(l[1]-l[0]);
}

VP convex(VP v){
    VP ret;
    int n = v.size();
    sort(v.begin(), v.end());
    for(int i=0; i<n; i++){
        while((int)ret.size()>1 && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    int t = ret.size();
    for(int i=n-2; i>=0; i--){
        while((int)ret.size()>t && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    if((int)ret.size() > 1) ret.pop_back();
    return ret;
}

double tri_search(const VP &c, int sp, int num){
    int n = c.size();
    int lb=sp, ub=sp+num;
    L base(c[sp], c[(sp+num)%n]);
    while(lb < ub){
        int mid = (lb +ub)/2;
        if(distanceLP(base, c[mid%n]) < distanceLP(base, c[(mid+1)%n])){
            lb = mid+1;
        }else{
            ub = mid;
        }
    }
    return distanceLP(base, c[lb%n]);
}

int main(){
    int n;
    cin >> n;
    VP p(n);
    for(int i=0; i<n; i++){
        int x,y;
        cin >> x >> y;
        p[i] = P(x, y);
    }

    VP c = convex(p);
    //凸包が三角形の場合はその頂点3つ+内部の1点
    if((int)c.size() == 3){
        double ans = 0;
        for(int i=0; i<n; i++){
            if(p[i]==c[0] || p[i]==c[1] || p[i]==c[2]) continue;
            for(int j=0; j<3; j++){
                L base(c[j], c[(j+1)%3]);
                double h = distanceLP(base, c[(j+2)%3]) -distanceLP(base, p[i]);
                ans = max(ans, abs(base[1] -base[0]) *h /2);
            }
        }
        cout << fixed << setprecision(1);
        cout << ans << endl;
        return 0;
    }

    //それ以外の場合は凸包上の4点(2点を決めて両側を3分探索)
    double ans = 0;
    n = c.size();
    for(int i=0; i<n; i++){
        for(int j=i+2; j<n; j++){
            double h1 = tri_search(c, i, j-i);
            double h2 = tri_search(c, j, n-(j-i));
            double blen = abs(c[i] -c[j]);
            ans = max(ans, blen *(h1 +h2) /2);
        }
    }
    cout << fixed << setprecision(1);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 740
memory_kb: 3428
final_rank: 5

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-6)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;
  Point(double x = 0,double y = 0): x(x),y(y){}
  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }
  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }
  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }
};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

Polygon andrewScan(Polygon s) {
  Polygon u,l;
  if(s.size() < 3)return s;

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

  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);

  for(int i=2;i<s.size();i++) {
      for(int n=u.size();n >= 2 && ccw(u[n-2],u[n-1],s[i]) != CLOCKWISE; n--)
        u.pop_back();
      u.push_back(s[i]);
    }

  for(int i=s.size()-3; i>=0 ; i--) {
      for(int n=l.size(); n >= 2 && ccw(l[n-2],l[n-1],s[i]) != CLOCKWISE; n--)
        l.pop_back();
      l.push_back(s[i]);
    }

  reverse(l.begin(),l.end());

  for(int i = u.size()-2; i >= 1; i--) l.push_back(u[i]);

  return l;
}

inline double heron(Point A,Point B,Point C){
  double a = abs(B-C);
  double b = abs(A-C);
  double c = abs(A-B);
  double s = ( a + b + c ) / 2;
  return sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
}

// -----------------------------------------------------------

const int MAX_V = 1510;
int V,nV;
vector<Point> ps,nps;

bool LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return equals(a,b) || a < b; }

static const double RATIO = ( 1 + sqrt(5.0) ) * 0.5;
double ternarySearch(int a,int b){
  int L = 1, R = ( a > b ) ? ( ( a - b - 1 + nV ) % nV ) : ( ( ( a + nV ) - b - 1  ) % nV );
  int sp = b;
  int pL = L, pR = R;


  rep(_,120){
    if( LT(heron(nps[((L+R*2)/3+sp)%nV],nps[a],nps[b]),heron(nps[((L*2+R)/3+sp)%nV],nps[a],nps[b])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
    if( R == pR && L == pL ) break;
    pR = R, pL = L;
  }

  /*
  double Lv = heron(nps[a],nps[b],nps[((int)((L*RATIO+R)/(1+RATIO))+sp)%nV]);
  double Rv = heron(nps[a],nps[b],nps[((int)((L+R*RATIO)/(1+RATIO))+sp)%nV]);
  rep(_,120){
    if( LT(Rv,Lv) ) {
      R = ( L + R * RATIO ) / ( 1 + RATIO );
      Rv = Lv;
      Lv = heron(nps[a],nps[b],nps[((int)((L*RATIO+R)/(1+RATIO))+sp)%nV]);
    } else {
      L = ( L * RATIO + R ) / ( 1 + RATIO );
      Lv = Rv;
      Rv = heron(nps[a],nps[b],nps[((int)((L+R*RATIO)/(1+RATIO))+sp)%nV]);
    }
    if( R == pR && L == pL ) break;
    pR = R, pL = L;
  }
  
  if( LT(Rv,Lv) ) R = ( L + R * RATIO ) / ( 1 + RATIO );
  else            L = ( L * RATIO + R ) / ( 1 + RATIO );
  */
  return heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]);
}

void compute(){
  nps = andrewScan(ps);
  nV = nps.size();  
  double maxi = 0;
  if( nV == 3 ) {
    rep(i,V) {
      if( nps[0] == ps[i] || nps[1] == ps[i] || nps[2] == ps[i] ) continue;
      double area1 = heron(nps[0],nps[1],ps[i]);
      double area2 = heron(nps[1],nps[2],ps[i]);
      double area3 = heron(nps[2],nps[0],ps[i]);
      double area4 = heron(nps[0],nps[1],nps[2]);
      maxi = max(maxi,area4-min(area1,min(area2,area3)));
    }
  } else {
    rep(i,nV) REP(j,i+2,nV) maxi = max(maxi,ternarySearch(i,j)+ternarySearch(j,i));
  }
  printf("%.1f\n",maxi);
}

int main(){
  scanf("%d",&V);
  ps.resize(V);
  rep(i,V) scanf("%lf %lf",&ps[i].x,&ps[i].y);
  compute();
  return 0;
}
accuracy: 1
time_ms: 1990
memory_kb: 1380
final_rank: 6

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-6)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;
  Point(double x = 0,double y = 0): x(x),y(y){}
  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }
  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }
  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }
};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

Polygon andrewScan(Polygon s) {
  Polygon u,l;
  if(s.size() < 3)return s;

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

  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);

  for(int i=2;i<s.size();i++) {
      for(int n=u.size();n >= 2 && ccw(u[n-2],u[n-1],s[i]) != CLOCKWISE; n--)
        u.pop_back();
      u.push_back(s[i]);
    }

  for(int i=s.size()-3; i>=0 ; i--) {
      for(int n=l.size(); n >= 2 && ccw(l[n-2],l[n-1],s[i]) != CLOCKWISE; n--)
        l.pop_back();
      l.push_back(s[i]);
    }

  reverse(l.begin(),l.end());

  for(int i = u.size()-2; i >= 1; i--) l.push_back(u[i]);

  return l;
}

inline double heron(Point A,Point B,Point C){
  double a = abs(B-C);
  double b = abs(A-C);
  double c = abs(A-B);
  double s = ( a + b + c ) / 2;
  return sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
}

// -----------------------------------------------------------

const int MAX_V = 1510;
int V,nV;
vector<Point> ps,nps;

bool LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return equals(a,b) || a < b; }

static const double RATIO = ( 1 + sqrt(5.0) ) * 0.5;
double ternarySearch(int a,int b){
  int L = 1, R = ( a > b ) ? ( ( a - b - 1 + nV ) % nV ) : ( ( ( a + nV ) - b - 1  ) % nV );
  int sp = b;
  int pL = L, pR = R;

  /*
  rep(_,120){
    if( LT(heron(nps[((L+R*2)/3+sp)%nV],nps[a],nps[b]),heron(nps[((L*2+R)/3+sp)%nV],nps[a],nps[b])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
    if( R == pR && L == pL ) break;
    pR = R, pL = L;
  }
  */
  double Lv = heron(nps[a],nps[b],nps[((int)((L*RATIO+R)/(1+RATIO))+sp)%nV]);
  double Rv = heron(nps[a],nps[b],nps[((int)((L+R*RATIO)/(1+RATIO))+sp)%nV]);
  rep(_,120){
    if( LT(Rv,Lv) ) {
      R = ( L + R * RATIO ) / ( 1 + RATIO );
      Rv = Lv;
      Lv = heron(nps[a],nps[b],nps[((int)((L*RATIO+R)/(1+RATIO))+sp)%nV]);
    } else {
      L = ( L * RATIO + R ) / ( 1 + RATIO );
      Lv = Rv;
      Rv = heron(nps[a],nps[b],nps[((int)((L+R*RATIO)/(1+RATIO))+sp)%nV]);
    }
    if( R == pR && L == pL ) break;
    pR = R, pL = L;
  }
  
  if( LT(Rv,Lv) ) R = ( L + R * RATIO ) / ( 1 + RATIO );
  else            L = ( L * RATIO + R ) / ( 1 + RATIO );

  return heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]);
}

void compute(){
  nps = andrewScan(ps);
  nV = nps.size();  
  double maxi = 0;
  if( nV == 3 ) {
    rep(i,V) {
      if( nps[0] == ps[i] || nps[1] == ps[i] || nps[2] == ps[i] ) continue;
      double area1 = heron(nps[0],nps[1],ps[i]);
      double area2 = heron(nps[1],nps[2],ps[i]);
      double area3 = heron(nps[2],nps[0],ps[i]);
      double area4 = heron(nps[0],nps[1],nps[2]);
      maxi = max(maxi,area4-min(area1,min(area2,area3)));
    }
  } else {
    rep(i,nV) REP(j,i+2,nV) maxi = max(maxi,ternarySearch(i,j)+ternarySearch(j,i));
  }
  printf("%.1f\n",maxi);
}

int main(){
  scanf("%d",&V);
  ps.resize(V);
  rep(i,V) scanf("%lf %lf",&ps[i].x,&ps[i].y);
  compute();
  return 0;
}
accuracy: 0.3125
time_ms: 1930
memory_kb: 1380
final_rank: 11

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-6)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad ????§???????????????¢?????§?????????????????¨
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// ??????????????¢????????????
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev ?????? cur ????????£??? next ????????????????§????????±???????
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

Polygon andrewScan(Polygon s) {
  Polygon u,l;
  if(s.size() < 3)return s;

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

  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);

  for(int i=2;i<s.size();i++) {
      for(int n=u.size();n >= 2 && ccw(u[n-2],u[n-1],s[i]) != CLOCKWISE; n--)
        u.pop_back();
      u.push_back(s[i]);
    }

  for(int i=s.size()-3; i>=0 ; i--) {
      for(int n=l.size(); n >= 2 && ccw(l[n-2],l[n-1],s[i]) != CLOCKWISE; n--)
        l.pop_back();
      l.push_back(s[i]);
    }

  reverse(l.begin(),l.end());

  for(int i = u.size()-2; i >= 1; i--) l.push_back(u[i]);

  return l;
}

inline double heron(Point A,Point B,Point C){
  double a = abs(B-C);
  double b = abs(A-C);
  double c = abs(A-B);
  double s = ( a + b + c ) / 2;
  return sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
}

// -----------------------------------------------------------

const int MAX_V = 1510;
int V,nV;
vector<Point> ps,nps;

bool LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return equals(a,b) || a < b; }

vector<int> buf;
double ternarySearch(int a,int b){
  //cout << "-(" << a << "," << b << ")-" << endl;
  //int L = 1, R = ( a > b ) ? ( ( b - a + nV ) % nV ) : ( ( a - 1 - b + nV) % nV );
  int L = 1;
  int R = ( a > b ) ? ( ( a - b - 1 + nV ) % nV ) : ( ( ( a + nV ) - b - 1  ) % nV );
  //cout << "L = " << L << " R = " << R << endl;
  int sp = b;
  int pL = L, pR = R;

  rep(_,120){
    if( LT(heron(nps[((L+R*2)/3+sp)%nV],nps[a],nps[b]),heron(nps[((L*2+R)/3+sp)%nV],nps[a],nps[b])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
    if( R == pR && L == pL ) break;
    pR = R, pL = L;
    //if( prev == ((int)((L+R)*0.5+sp))%nV ) break;
    //prev = (int)((L+R)*0.5+sp)%nV;
  }
  /*
  puts("");
  cout << ((int)((L+R)*0.5)+sp)%nV << endl;
  cout << nps[((int)((L+R)*0.5)+sp)%nV] << endl;
  cout << heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]) << endl;
  */
  return heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]);
}

void compute(){
  nps = andrewScan(ps);
  nV = nps.size();  
  //rep(i,nV) cout << nps[i] << endl;
  //puts("");
  double maxi = 0;
  if( nV == 3 ) {
    rep(i,V) {
      if( nps[0] == ps[i] || nps[1] == ps[i] || nps[2] == ps[i] ) continue;
      double area1 = heron(nps[0],nps[1],ps[i]);
      double area2 = heron(nps[1],nps[2],ps[i]);
      double area3 = heron(nps[2],nps[0],ps[i]);
      double area4 = heron(nps[0],nps[1],nps[2]);
      maxi = max(maxi,area4-min(area1,min(area2,area3)));
    }
  } else {
    /*
    double a = ternarySearch(1,4);
    double b = ternarySearch(4,1);
    cout << a + b << endl;
    maxi = a + b;
    */
    rep(i,nV) REP(j,i+2,nV) {
      double LLVM = 5136;
      double tmp = ternarySearch(i,j)+ternarySearch(j,i);
      if( equals(tmp,LLVM) && !equals(maxi,tmp) ) {
        //cout << i << " !!! " << j << endl;
      }
      maxi = max(maxi,tmp);
    }
  }
  printf("%.1f\n",maxi);
}

int main(){
  /*
  Point p[3];
  rep(i,3) cin >> p[i].x >> p[i].y;
  printf("%.1lf\n",heron(p[0],p[1],p[2]));

  cin >> V;
  ps.resize(V);
  rep(i,V) cin >> ps[i].x >> ps[i].y;
  int L = 1, R = V - 2;
  int sp = 0;
  rep(_,30){
    if( LT(heron(ps[((L+R*2)/3+sp)%V],ps[0],ps[V-1]),heron(ps[((L*2+R)/3+sp)%V],ps[0],ps[V-1])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
  }
  cout << 0 << " " << ((int)((L+R)*0.5)+sp)%V << " " << V-1 << endl; 
  cout << ps[0] << " " << ps[((int)((L+R)*0.5)+sp)%V] << " " << ps[V-1] << endl;
  cout << heron(ps[(int)(((L+R)*0.5)+sp)%V],ps[0],ps[V-1]) << endl;
  return 0;
  */
  scanf("%d",&V);
  ps.resize(V);
  rep(i,V) scanf("%lf %lf",&ps[i].x,&ps[i].y);
  compute();
  return 0;
}
accuracy: 1
time_ms: 2000
memory_kb: 1380
final_rank: 7

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-6)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad ????§???????????????¢?????§?????????????????¨
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// ??????????????¢????????????
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev ?????? cur ????????£??? next ????????????????§????????±???????
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

Polygon andrewScan(Polygon s) {
  Polygon u,l;
  if(s.size() < 3)return s;

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

  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);

  for(int i=2;i<s.size();i++) {
      for(int n=u.size();n >= 2 && ccw(u[n-2],u[n-1],s[i]) != CLOCKWISE; n--)
        u.pop_back();
      u.push_back(s[i]);
    }

  for(int i=s.size()-3; i>=0 ; i--) {
      for(int n=l.size(); n >= 2 && ccw(l[n-2],l[n-1],s[i]) != CLOCKWISE; n--)
        l.pop_back();
      l.push_back(s[i]);
    }

  reverse(l.begin(),l.end());

  for(int i = u.size()-2; i >= 1; i--) l.push_back(u[i]);

  return l;
}

inline double heron(Point A,Point B,Point C){
  double a = abs(B-C);
  double b = abs(A-C);
  double c = abs(A-B);
  double s = ( a + b + c ) / 2;
  return sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
}

// -----------------------------------------------------------

const int MAX_V = 1510;
int V,nV;
vector<Point> ps,nps;

bool LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return equals(a,b) || a < b; }

vector<int> buf;
double ternarySearch(int a,int b){
  //cout << "-(" << a << "," << b << ")-" << endl;
  //int L = 1, R = ( a > b ) ? ( ( b - a + nV ) % nV ) : ( ( a - 1 - b + nV) % nV );
  int L = 1;
  int R = ( a > b ) ? ( ( a - b - 1 + nV ) % nV ) : ( ( ( a + nV ) - b - 1  ) % nV );
  //cout << "L = " << L << " R = " << R << endl;
  int sp = b;
  int prev = -1;
  rep(_,120){
    if( LT(heron(nps[((L+R*2)/3+sp)%nV],nps[a],nps[b]),heron(nps[((L*2+R)/3+sp)%nV],nps[a],nps[b])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
    if( prev == ((int)((L+R)*0.5+sp))%nV ) break;
    prev = (int)((L+R)*0.5+sp)%nV;
  }
  /*
  puts("");
  cout << ((int)((L+R)*0.5)+sp)%nV << endl;
  cout << nps[((int)((L+R)*0.5)+sp)%nV] << endl;
  cout << heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]) << endl;
  */
  return heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]);
}

void compute(){
  nps = andrewScan(ps);
  nV = nps.size();  
  //rep(i,nV) cout << nps[i] << endl;
  //puts("");
  double maxi = 0;
  if( nV == 3 ) {
    rep(i,V) {
      if( nps[0] == ps[i] || nps[1] == ps[i] || nps[2] == ps[i] ) continue;
      double area1 = heron(nps[0],nps[1],ps[i]);
      double area2 = heron(nps[1],nps[2],ps[i]);
      double area3 = heron(nps[2],nps[0],ps[i]);
      double area4 = heron(nps[0],nps[1],nps[2]);
      maxi = max(maxi,area4-min(area1,min(area2,area3)));
    }
  } else {
    /*
    double a = ternarySearch(1,4);
    double b = ternarySearch(4,1);
    cout << a + b << endl;
    maxi = a + b;
    */
    rep(i,nV) REP(j,i+2,nV) {
      double LLVM = 5136;
      double tmp = ternarySearch(i,j)+ternarySearch(j,i);
      if( equals(tmp,LLVM) && !equals(maxi,tmp) ) {
        //cout << i << " !!! " << j << endl;
      }
      maxi = max(maxi,tmp);
    }
  }
  printf("%.1f\n",maxi);
}

int main(){
  /*
  Point p[3];
  rep(i,3) cin >> p[i].x >> p[i].y;
  printf("%.1lf\n",heron(p[0],p[1],p[2]));

  cin >> V;
  ps.resize(V);
  rep(i,V) cin >> ps[i].x >> ps[i].y;
  int L = 1, R = V - 2;
  int sp = 0;
  rep(_,30){
    if( LT(heron(ps[((L+R*2)/3+sp)%V],ps[0],ps[V-1]),heron(ps[((L*2+R)/3+sp)%V],ps[0],ps[V-1])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
  }
  cout << 0 << " " << ((int)((L+R)*0.5)+sp)%V << " " << V-1 << endl; 
  cout << ps[0] << " " << ps[((int)((L+R)*0.5)+sp)%V] << " " << ps[V-1] << endl;
  cout << heron(ps[(int)(((L+R)*0.5)+sp)%V],ps[0],ps[V-1]) << endl;
  return 0;
  */
  scanf("%d",&V);
  ps.resize(V);
  rep(i,V) scanf("%lf %lf",&ps[i].x,&ps[i].y);
  compute();
  return 0;
}
accuracy: 0.3541666666666667
time_ms: 2280
memory_kb: 1380
final_rank: 10

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-6)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad ????§???????????????¢?????§?????????????????¨
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// ??????????????¢????????????
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev ?????? cur ????????£??? next ????????????????§????????±???????
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

Polygon andrewScan(Polygon s) {
  Polygon u,l;
  if(s.size() < 3)return s;

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

  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);

  for(int i=2;i<s.size();i++) {
      for(int n=u.size();n >= 2 && ccw(u[n-2],u[n-1],s[i]) != CLOCKWISE; n--)
        u.pop_back();
      u.push_back(s[i]);
    }

  for(int i=s.size()-3; i>=0 ; i--) {
      for(int n=l.size(); n >= 2 && ccw(l[n-2],l[n-1],s[i]) != CLOCKWISE; n--)
        l.pop_back();
      l.push_back(s[i]);
    }

  reverse(l.begin(),l.end());

  for(int i = u.size()-2; i >= 1; i--) l.push_back(u[i]);

  return l;
}

inline double heron(Point A,Point B,Point C){
  double a = abs(B-C);
  double b = abs(A-C);
  double c = abs(A-B);
  double s = ( a + b + c ) / 2;
  return sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
}

// -----------------------------------------------------------

const int MAX_V = 1510;
int V,nV;
vector<Point> ps,nps;

bool LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return equals(a,b) || a < b; }

vector<int> buf;
double ternarySearch(int a,int b){
  //cout << "-(" << a << "," << b << ")-" << endl;
  //int L = 1, R = ( a > b ) ? ( ( b - a + nV ) % nV ) : ( ( a - 1 - b + nV) % nV );
  int L = 1;
  int R = ( a > b ) ? ( ( a - b - 1 + nV ) % nV ) : ( ( ( a + nV ) - b - 1  ) % nV );
  //cout << "L = " << L << " R = " << R << endl;
  int sp = b;
  int prev = -1;
  rep(_,120){
    if( LT(heron(nps[((L+R*2)/3+sp)%nV],nps[a],nps[b]),heron(nps[((L*2+R)/3+sp)%nV],nps[a],nps[b])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
    if( prev == ((int)((L+R)*0.5+sp))%nV ) break;
    prev = (int)((L+R)*0.5+sp)%nV;
  }
  /*
  puts("");
  cout << ((int)((L+R)*0.5)+sp)%nV << endl;
  cout << nps[((int)((L+R)*0.5)+sp)%nV] << endl;
  cout << heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]) << endl;
  */
  return heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]);
}

void compute(){
  nps = andrewScan(ps);
  nV = nps.size();  
  //rep(i,nV) cout << nps[i] << endl;
  //puts("");
  double maxi = 0;
  if( nV == 3 ) {
    rep(i,V) {
      if( nps[0] == ps[i] || nps[1] == ps[i] || nps[2] == ps[i] ) continue;
      double area1 = heron(nps[0],nps[1],ps[i]);
      double area2 = heron(nps[1],nps[2],ps[i]);
      double area3 = heron(nps[2],nps[0],ps[i]);
      double area4 = heron(nps[0],nps[1],nps[2]);
      maxi = max(maxi,area4-min(area1,min(area2,area3)));
    }
  } else {
    /*
    double a = ternarySearch(1,4);
    double b = ternarySearch(4,1);
    cout << a + b << endl;
    maxi = a + b;
    */
    rep(i,nV) REP(j,i+2,nV-1) {
      double LLVM = 5136;
      double tmp = ternarySearch(i,j)+ternarySearch(j,i);
      if( equals(tmp,LLVM) && !equals(maxi,tmp) ) {
        //cout << i << " !!! " << j << endl;
      }
      maxi = max(maxi,tmp);
    }
  }
  printf("%.1f\n",maxi);
}

int main(){
  /*
  Point p[3];
  rep(i,3) cin >> p[i].x >> p[i].y;
  printf("%.1lf\n",heron(p[0],p[1],p[2]));

  cin >> V;
  ps.resize(V);
  rep(i,V) cin >> ps[i].x >> ps[i].y;
  int L = 1, R = V - 2;
  int sp = 0;
  rep(_,30){
    if( LT(heron(ps[((L+R*2)/3+sp)%V],ps[0],ps[V-1]),heron(ps[((L*2+R)/3+sp)%V],ps[0],ps[V-1])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
  }
  cout << 0 << " " << ((int)((L+R)*0.5)+sp)%V << " " << V-1 << endl; 
  cout << ps[0] << " " << ps[((int)((L+R)*0.5)+sp)%V] << " " << ps[V-1] << endl;
  cout << heron(ps[(int)(((L+R)*0.5)+sp)%V],ps[0],ps[V-1]) << endl;
  return 0;
  */
  scanf("%d",&V);
  ps.resize(V);
  rep(i,V) scanf("%lf %lf",&ps[i].x,&ps[i].y);
  compute();
  return 0;
}
accuracy: 0.125
time_ms: 2540
memory_kb: 1380
final_rank: 12

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-6)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad ????§???????????????¢?????§?????????????????¨
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// ??????????????¢????????????
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev ?????? cur ????????£??? next ????????????????§????????±???????
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

Polygon andrewScan(Polygon s) {
  Polygon u,l;
  if(s.size() < 3)return s;

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

  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);

  for(int i=2;i<s.size();i++) {
      for(int n=u.size();n >= 2 && ccw(u[n-2],u[n-1],s[i]) != CLOCKWISE; n--)
        u.pop_back();
      u.push_back(s[i]);
    }

  for(int i=s.size()-3; i>=0 ; i--) {
      for(int n=l.size(); n >= 2 && ccw(l[n-2],l[n-1],s[i]) != CLOCKWISE; n--)
        l.pop_back();
      l.push_back(s[i]);
    }

  reverse(l.begin(),l.end());

  for(int i = u.size()-2; i >= 1; i--) l.push_back(u[i]);

  return l;
}

inline double heron(Point A,Point B,Point C){
  double a = abs(B-C);
  double b = abs(A-C);
  double c = abs(A-B);
  double s = ( a + b + c ) / 2;
  return sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
}

// -----------------------------------------------------------

const int MAX_V = 1510;
int V,nV;
vector<Point> ps,nps;

bool LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return equals(a,b) || a < b; }

double ternarySearch(int a,int b){
  int L = 1, R = ( a < b ) ? ( ( b - a - 1 + nV ) % nV ) : ( ( a - 1 - b + nV) % nV );
  int sp = a;
  int prev = -1;
  rep(_,120){
    if( LT(heron(nps[((L+R*2)/3+sp)%nV],nps[a],nps[b]),heron(nps[((L*2+R)/3+sp)%nV],nps[a],nps[b])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
    if( prev == ((int)((L+R)*0.5+sp))%nV ) break;
    prev = (int)((L+R)*0.5+sp)%nV;
  }
  return heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]);
}

void compute(){
  nps = andrewScan(ps);
  nV = nps.size();  
  double maxi = 0;
  if( nV == 3 ) {
    rep(i,V) {
      if( nps[0] == ps[i] || nps[1] == ps[i] || nps[2] == ps[i] ) continue;
      double area1 = heron(nps[0],nps[1],ps[i]);
      double area2 = heron(nps[1],nps[2],ps[i]);
      double area3 = heron(nps[2],nps[0],ps[i]);
      double area4 = heron(nps[0],nps[1],nps[2]);
      maxi = max(maxi,area4-min(area1,min(area2,area3)));
    }
  } else {
    rep(i,nV) REP(j,i+1,nV) maxi = max(maxi,ternarySearch(i,j)+ternarySearch(j,i));
  }
  printf("%.1f\n",maxi);
}

int main(){
  scanf("%d",&V);
  ps.resize(V);
  rep(i,V) scanf("%lf %lf",&ps[i].x,&ps[i].y);
  compute();
  return 0;
}
accuracy: 0.020833333333333332
time_ms: 2030
memory_kb: 1380
final_rank: 15

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-4)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad ????§???????????????¢?????§?????????????????¨
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// ??????????????¢????????????
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev ?????? cur ????????£??? next ????????????????§????????±???????
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

Polygon andrewScan(Polygon s) {
  Polygon u,l;
  if(s.size() < 3)return s;

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

  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);

  for(int i=2;i<s.size();i++) {
      for(int n=u.size();n >= 2 && ccw(u[n-2],u[n-1],s[i]) != CLOCKWISE; n--)
        u.pop_back();
      u.push_back(s[i]);
    }

  for(int i=s.size()-3; i>=0 ; i--) {
      for(int n=l.size(); n >= 2 && ccw(l[n-2],l[n-1],s[i]) != CLOCKWISE; n--)
        l.pop_back();
      l.push_back(s[i]);
    }

  reverse(l.begin(),l.end());

  for(int i = u.size()-2; i >= 1; i--) l.push_back(u[i]);

  return l;
}

inline double heron(Point A,Point B,Point C){
  double a = abs(B-C);
  double b = abs(A-C);
  double c = abs(A-B);
  double s = ( a + b + c ) / 2;
  return sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
}

// -----------------------------------------------------------

const int MAX_V = 1510;
int V,nV;
vector<Point> ps,nps;

bool LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return equals(a,b) || a < b; }

double ternarySearch(int a,int b){
  int L = 1, R = ( a < b ) ? ( ( b - a - 1 + nV ) % nV ) : ( ( a - 1 - b + nV) % nV );
  int sp = a;
  int prev = -1;
  rep(_,120){
    if( LT(heron(nps[((L+R*2)/3+sp)%nV],nps[a],nps[b]),heron(nps[((L*2+R)/3+sp)%nV],nps[a],nps[b])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
    if( prev == ((int)((L+R)*0.5+sp))%nV ) break;
    prev = (int)((L+R)*0.5+sp)%nV;
  }
  return heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]);
}

void compute(){
  nps = andrewScan(ps);
  nV = nps.size();  
  double maxi = 0;
  if( nV == 3 ) {
    rep(i,V) {
      if( nps[0] == ps[i] || nps[1] == ps[i] || nps[2] == ps[i] ) continue;
      double area1 = heron(nps[0],nps[1],ps[i]);
      double area2 = heron(nps[1],nps[2],ps[i]);
      double area3 = heron(nps[2],nps[0],ps[i]);
      double area4 = heron(nps[0],nps[1],nps[2]);
      maxi = max(maxi,area4-min(area1,min(area2,area3)));
    }
  } else {
    rep(i,nV) REP(j,i+1,nV-1) maxi = max(maxi,ternarySearch(i,j)+ternarySearch(j,i));
  }
  printf("%.1f\n",maxi);
}

int main(){
  scanf("%d",&V);
  ps.resize(V);
  rep(i,V) scanf("%lf %lf",&ps[i].x,&ps[i].y);
  compute();
  return 0;
}
accuracy: 0.020833333333333332
time_ms: 2020
memory_kb: 1380
final_rank: 14

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-6)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad ????§???????????????¢?????§?????????????????¨
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// ??????????????¢????????????
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev ?????? cur ????????£??? next ????????????????§????????±???????
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

Polygon andrewScan(Polygon s) {
  Polygon u,l;
  if(s.size() < 3)return s;

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

  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);

  for(int i=2;i<s.size();i++) {
      for(int n=u.size();n >= 2 && ccw(u[n-2],u[n-1],s[i]) != CLOCKWISE; n--)
        u.pop_back();
      u.push_back(s[i]);
    }

  for(int i=s.size()-3; i>=0 ; i--) {
      for(int n=l.size(); n >= 2 && ccw(l[n-2],l[n-1],s[i]) != CLOCKWISE; n--)
        l.pop_back();
      l.push_back(s[i]);
    }

  reverse(l.begin(),l.end());

  for(int i = u.size()-2; i >= 1; i--) l.push_back(u[i]);

  return l;
}

inline double heron(Point A,Point B,Point C){
  double a = abs(B-C);
  double b = abs(A-C);
  double c = abs(A-B);
  double s = ( a + b + c ) / 2;
  return sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
}

// -----------------------------------------------------------

const int MAX_V = 1510;
int V,nV;
vector<Point> ps,nps;

bool LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return equals(a,b) || a < b; }

double ternarySearch(int a,int b){
  int L = 1, R = ( a < b ) ? ( ( b - a - 1 + nV ) % nV ) : ( ( a - 1 - b + nV) % nV );
  int sp = a;
  rep(_,50){
    if( LT(heron(nps[((L+R*2)/3+sp)%nV],nps[a],nps[b]),heron(nps[((L*2+R)/3+sp)%nV],nps[a],nps[b])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
  }
  return heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]);
}

void compute(){
  nps = andrewScan(ps);
  nV = nps.size();  
  double maxi = 0;
  if( nV == 3 ) {
    rep(i,V) {
      if( nps[0] == ps[i] || nps[1] == ps[i] || nps[2] == ps[i] ) continue;
      double area1 = heron(nps[0],nps[1],ps[i]);
      double area2 = heron(nps[1],nps[2],ps[i]);
      double area3 = heron(nps[2],nps[0],ps[i]);
      double area4 = heron(nps[0],nps[1],nps[2]);
      maxi = max(maxi,area4-min(area1,min(area2,area3)));
    }
  } else {
    rep(i,nV) REP(j,i+1,nV-1) maxi = max(maxi,ternarySearch(i,j)+ternarySearch(j,i));
  }
  printf("%.1f\n",maxi);
}

int main(){
  scanf("%d",&V);
  ps.resize(V);
  rep(i,V) scanf("%lf %lf",&ps[i].x,&ps[i].y);
  compute();
  return 0;
}
accuracy: 0.020833333333333332
time_ms: 7730
memory_kb: 1380
final_rank: 17

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-6)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad ????§???????????????¢?????§?????????????????¨
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// ??????????????¢????????????
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev ?????? cur ????????£??? next ????????????????§????????±???????
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

Polygon andrewScan(Polygon s) {
  Polygon u,l;
  if(s.size() < 3)return s;

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

  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);

  for(int i=2;i<s.size();i++) {
      for(int n=u.size();n >= 2 && ccw(u[n-2],u[n-1],s[i]) != CLOCKWISE; n--)
        u.pop_back();
      u.push_back(s[i]);
    }

  for(int i=s.size()-3; i>=0 ; i--) {
      for(int n=l.size(); n >= 2 && ccw(l[n-2],l[n-1],s[i]) != CLOCKWISE; n--)
        l.pop_back();
      l.push_back(s[i]);
    }

  reverse(l.begin(),l.end());

  for(int i = u.size()-2; i >= 1; i--) l.push_back(u[i]);

  return l;
}

inline double heron(Point A,Point B,Point C){
  double a = abs(B-C);
  double b = abs(A-C);
  double c = abs(A-B);
  double s = ( a + b + c ) / 2;
  return sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
}

// -----------------------------------------------------------

const int MAX_V = 1510;
int V,nV;
vector<Point> ps,nps;

bool LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return equals(a,b) || a < b; }

double ternarySearch(int a,int b){
  int L = 1, R = ( a < b ) ? ( ( b - a - 1 + nV ) % nV ) : ( ( a - 1 - b + nV) % nV );
  int sp = a;
  rep(_,30){
    if( LT(heron(nps[((L+R*2)/3+sp)%nV],nps[a],nps[b]),heron(nps[((L*2+R)/3+sp)%nV],nps[a],nps[b])) ) {
      R = ( L + R * 2 ) / 3;
    } else {
      L = ( L * 2 + R ) / 3;
    }
  }
  return heron(nps[(int)(((L+R)*0.5)+sp)%nV],nps[a],nps[b]);
}

void compute(){
  nps = andrewScan(ps);
  nV = nps.size();  
  double maxi = 0;
  if( nV == 3 ) {
    rep(i,V) {
      if( nps[0] == ps[i] || nps[1] == ps[i] || nps[2] == ps[i] ) continue;
      double area1 = heron(nps[0],nps[1],ps[i]);
      double area2 = heron(nps[1],nps[2],ps[i]);
      double area3 = heron(nps[2],nps[0],ps[i]);
      double area4 = heron(nps[0],nps[1],nps[2]);
      maxi = max(maxi,area4-min(area1,min(area2,area3)));
    }
  } else {
    rep(i,nV) REP(j,i+1,nV-1) maxi = max(maxi,ternarySearch(i,j)+ternarySearch(j,i));
  }
  printf("%.1f\n",maxi);
}

int main(){
  scanf("%d",&V);
  ps.resize(V);
  rep(i,V) scanf("%lf %lf",&ps[i].x,&ps[i].y);
  compute();
  return 0;
}
accuracy: 0.020833333333333332
time_ms: 4680
memory_kb: 1376
final_rank: 16

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

class Point
{
public:
    int y, x;
    Point(){
        y = x = 0;
    }
    Point(int y0, int x0){
        y = y0;
        x = x0;
    }
    Point operator+(const Point& p) const{
        return Point(y + p.y, x + p.x);
    }
    Point operator-(const Point& p) const{
        return Point(y - p.y, x - p.x);
    }
    Point operator*(int a) const{
        return Point(y * a, x * a);
    }
    long long cross(const Point& p) const{
        return (long long)x * p.y - (long long)y * p.x; // |a|*|b|*sin慮
    }
    bool operator==(const Point& p) const{
        return x == p.x && y == p.y;
    }
    bool operator<(const Point& p) const{
        return x < p.x || (x == p.x && y < p.y);
    }
};

long long polygonArea(const vector<Point>& p)
{
    int n = p.size();
    long long ret = 0;
    for(int i=0; i<n; ++i)
        ret += p[i].cross(p[(i+1)%n]);
    return abs(ret);
}

void convexHull(const vector<Point>& p0, vector<Point>& cv)
{
    vector<Point> p = p0;
    sort(p.begin(), p.end());
    int n = p.size();

    int j = 0;
    cv.clear();
    for(int i=0; i<2*n-1; ++i){
        Point tmp = (i<n? p[i]:p[2*(n-1)-i]);
        while(j >= 2 && (tmp-cv[j-2]).cross(cv[j-1]-cv[j-2]) < 0){
            cv.pop_back();
            -- j;
        }
        cv.push_back(tmp);
        ++ j;
    }
    cv.pop_back();
}

long long solve(vector<Point>& p, int left, int right)
{
    int n = p.size();

    int l = 1;
    int r = (right - left + n) % n - 1;

    vector<Point> p2(3);
    p2[0] = p[left];
    p2[1] = p[right];

    while(l < r){
        int m1 = (l*2 + r) / 3;
        int m2 = (l + r*2 + 1) / 3;

        p2[2] = p[(left + m1) % n];
        long long s1 = polygonArea(p2);
        p2[2] = p[(left + m2) % n];
        long long s2 = polygonArea(p2);

        if(s1 < s2)
            l = m1 + 1;
        else
            r = m2 - 1;
    }

    p2[2] = p[(left + l) % n];
    return polygonArea(p2);
}

int main()
{
    int n;
    cin >> n;
    vector<Point> p(n);
    for(int i=0; i<n; ++i)
        cin >> p[i].x >> p[i].y;

    vector<Point> cv;
    convexHull(p, cv);
    int m = cv.size();

    long long ret = 0;

    if(m == 3){
        for(int i=0; i<n; ++i){
            if(find(cv.begin(), cv.end(), p[i]) != cv.end())
                continue;
            for(int j=0; j<3; ++j){
                vector<Point> p2 = cv;
                p2.insert(p2.begin()+j, p[i]);
                ret = max(ret, polygonArea(p2));
            }
        }
    }else{
        for(int i=0; i<m; ++i){
            for(int j=i+2; j<m; ++j){
                if(i == 0 && j == m-1)
                    continue;
                ret = max(ret, solve(cv, i, j) + solve(cv, j, i));
            }
        }
    }

    cout << (ret / 2) << '.';
    if(ret % 2 == 0)
        cout << '0' << endl;
    else
        cout << '5' << endl;

    return 0;
}
accuracy: 1
time_ms: 1150
memory_kb: 1248
final_rank: 3

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

class Point
{
public:
    int y, x;
    Point(){
        y = x = 0;
    }
    Point(int y0, int x0){
        y = y0;
        x = x0;
    }
    Point operator+(const Point& p) const{
        return Point(y + p.y, x + p.x);
    }
    Point operator-(const Point& p) const{
        return Point(y - p.y, x - p.x);
    }
    Point operator*(int a) const{
        return Point(y * a, x * a);
    }
    int length2() const{
        return y * y + x * x;
    }
    int dist2(const Point& p) const{
        return (y - p.y) * (y - p.y) + (x - p.x) * (x - p.x);
    }
    int dot(const Point& p) const{
        return y * p.y + x * p.x; // |a|*|b|*cos慮
    }
    int cross(const Point& p) const{
        return x * p.y - y * p.x; // |a|*|b|*sin慮
    }
    bool operator==(const Point& p) const{
        return x == p.x && y == p.y;
    }
    bool operator<(const Point& p) const{
        return x < p.x || (x == p.x && y < p.y);
    }
};

double polygonArea(const vector<Point>& p)
{
    int n = p.size();
    double ret = 0.0;
    for(int i=0; i<n; ++i)
        ret += p[i].cross(p[(i+1)%n]);
    return abs(ret) / 2.0;
}

void convexHull(const vector<Point>& p0, vector<Point>& cv)
{
    vector<Point> p = p0;
    sort(p.begin(), p.end());
    int n = p.size();

    int j = 0;
    cv.clear();
    for(int i=0; i<2*n-1; ++i){
        Point tmp = (i<n? p[i]:p[2*(n-1)-i]);
        while(j >= 2 && (tmp-cv[j-2]).cross(cv[j-1]-cv[j-2]) < 0){
            cv.pop_back();
            -- j;
        }
        cv.push_back(tmp);
        ++ j;
    }
    cv.pop_back();
}

double solve(vector<Point>& p, int left, int right)
{
    int n = p.size();

    int l = 1;
    int r = (right - left + n) % n - 1;

    vector<Point> p2(3);
    p2[0] = p[left];
    p2[1] = p[right];

    while(l < r){
        int m1 = (l*2 + r) / 3;
        int m2 = (l + r*2 + 1) / 3;

        p2[2] = p[(left + m1) % n];
        double s1 = polygonArea(p2);
        p2[2] = p[(left + m2) % n];
        double s2 = polygonArea(p2);

        if(s1 < s2)
            l = m1 + 1;
        else
            r = m2 - 1;
    }

    p2[2] = p[(left + l) % n];
    return polygonArea(p2);
}

int main()
{
    int n;
    cin >> n;
    vector<Point> p(n);
    for(int i=0; i<n; ++i)
        cin >> p[i].x >> p[i].y;

    vector<Point> cv;
    convexHull(p, cv);
    int m = cv.size();

    double ret = 0.0;

    if(m == 3){
        for(int i=0; i<n; ++i){
            if(find(cv.begin(), cv.end(), p[i]) != cv.end())
                continue;
            for(int j=0; j<3; ++j){
                vector<Point> p2 = cv;
                p2.insert(p2.begin()+j, p[i]);
                ret = max(ret, polygonArea(p2));
            }
        }
    }else{
        for(int i=0; i<m; ++i){
            for(int j=i+2; j<m; ++j){
                if(i == 0 && j == m-1)
                    continue;
                ret = max(ret, solve(cv, i, j) + solve(cv, j, i));
            }
        }
    }

    printf("%.1f\n", ret);

    return 0;
}
accuracy: 0.4583333333333333
time_ms: 1110
memory_kb: 1280
final_rank: 9

code_snippet: #include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double EPS=1e-5;
const double INF=1e77;

struct point{
	double x,y;
	point():x(0),y(0){}
	point(double x,double y):x(x),y(y){}
	point operator-(const point &a)const{ return point(x-a.x,y-a.y); }
};

bool operator< (const point &a,const point &b){ return a.x+EPS<b.x || abs(a.x-b.x)<EPS && a.y+EPS<b.y; }
bool operator!=(const point &a,const point &b){ return abs(a.x-b.x)>EPS || abs(a.y-b.y)>EPS; }

double cross(const point &a,const point &b){ return a.x*b.y-a.y*b.x; }

struct line{
	point a,b;
	line(const point &a,const point &b):a(a),b(b){}
};

typedef vector<point> polygon;

enum{CCW=1,CW=-1,ON=0};
int ccw(const point &a,const point &b,const point &c){
	double rdir=cross(b-a,c-a);
	if(rdir> EPS) return CCW;
	if(rdir<-EPS) return CW;
	return ON;
}

polygon convex_hull(vector<point> &P){
	int n=P.size();
	polygon CH;
	if(n<=1){
		CH.insert(CH.end(),P.begin(),P.end());
		return CH;
	}
	sort(P.begin(),P.end());

	rep(_,2){
		int m=0;
		vector<point> half(n);
		rep(i,n){
			half[m++]=P[i];
			while(m>=3 && ccw(half[m-3],half[m-2],half[m-1])!=CCW){
				half[m-2]=half[m-1];
				m--;
			}
		}
		CH.insert(CH.end(),half.begin(),half.begin()+m-1);
		reverse(P.begin(),P.end());
	}

	return CH;
}

double dist(const point &a,const point &b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double dist(const line &L,const point &p){
	return abs(cross(L.b-L.a,p-L.a))/dist(L.a,L.b);
}

double area(const point &a,const point &b,const point &c){
	return abs(cross(b-a,c-a))/2;
}

int main(){
	int n; scanf("%d",&n);
	vector<point> P(n);
	rep(i,n) scanf("%lf%lf",&P[i].x,&P[i].y);

	polygon CH=convex_hull(P);

	if(CH.size()==3){
		double A=INF;
		rep(i,n) if(P[i]!=CH[0] && P[i]!=CH[1] && P[i]!=CH[2]) { // テ・ツ?クテ・ツ個?、ツサツ・テ・ツ、ツ姪」ツ?ョテァツつケ
			A=min(A,dist(CH[0],CH[1])*dist(line(CH[0],CH[1]),P[i])/2);
			A=min(A,dist(CH[1],CH[2])*dist(line(CH[1],CH[2]),P[i])/2);
			A=min(A,dist(CH[2],CH[0])*dist(line(CH[2],CH[0]),P[i])/2);
		}
		printf("%.1f\n",area(CH[0],CH[1],CH[2])-A);
	}
	else{ // CH.size()>=4
		n=CH.size();
		CH.resize(2*n);
		rep(i,n) CH[n+i]=CH[i];

		double ans=0;
		rep(i,n) for(int j=i+1;j<n;j++) {
			if((j-i)%n==1 || (j-i)%n==n-1) continue;

			int lo=i,hi=j;
			while(lo<hi){
				int mi1=(lo+hi)/2,mi2=mi1+1;
				if(area(CH[i],CH[j],CH[mi1])<area(CH[i],CH[j],CH[mi2])) lo=mi1+1; else hi=mi2-1;
			}
			int k=lo;


			lo=j,hi=n+i;
			while(lo<hi){
				int mi1=(lo+hi)/2,mi2=mi1+1;
				if(area(CH[j],CH[n+i],CH[mi1])<area(CH[j],CH[n+i],CH[mi2])) lo=mi1+1; else hi=mi2-1;
			}
			int l=lo;

			ans=max(ans,area(CH[i],CH[j],CH[k])+area(CH[j],CH[n+i],CH[l]));
		}
		printf("%.1f\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 1228
final_rank: 1

code_snippet: #include<iostream>
#include<complex>
#include<vector>
#include<cmath>
#include<algorithm>
#include<cstdio>

using namespace std;

#define rep(i, n) for (int i = 0; i < int(n); ++i)

#define X real()
#define Y imag()

typedef long double D;
typedef complex<D> P;
typedef pair<P, P> L;
typedef vector<P> Pol;

const D INF = 1e40;
const D EPS = 1e-8;
const D PI = acos(-1);

int sig(D r) {return (r < -EPS) ? -1 : (r > EPS) ? 1 : 0;}
bool eq(D a, D b) {return abs(a - b) < EPS;}
bool near(P a, P b) {return abs(a - b) < EPS;}

// テ・ツ??ァツゥツ?
D dot(P a, P b) {return a.X * b.X + a.Y * b.Y;}
// テ・ツ、ツ姪ァツゥツ?
D det(P a, P b) {return a.X * b.Y - a.Y * b.X;}

// テァツキツ堙・ツ按?」ツ?ョテ」ツδ凖」ツつッテ」ツδ暗」ツδォ
P vec(L a) {return a.second - a.first;}

// テァツキツ堙・ツ按?bテ」ツ?ォテ・ツッツセテ」ツ?凖」ツつ凝ァツつケxテ」ツ?ョテ、ツスツ催ァツスツョ
enum CCW{FRONT = 1, RIGHT = 2, BACK = 4, LEFT = 8, ON = 16};
int ccw(L s, P p) {
  P a = vec(s);
  p -= s.first;
  D cr = det(a, p);
  if (eq(cr, 0)) {
    if (sig(dot(a, p)) < 0) return BACK;
    if (sig(norm(a) - norm(p)) < 0) return FRONT;
    return ON;
  }
  return (cr > 0) ? LEFT : RIGHT;
}

// ティツァツ津・ツコツヲ
D ang(P p) {D theta = arg(p); return sig(theta - PI) < 0 ? theta : -PI;}
// テヲツ慊嘉・ツ青妥ィツァツ津・ツコツヲ
D ang(P base, P a, P b) {return ang((b - base) / (a - base));}

// テ・ツーツ?・ツスツア
P proj(P a, P b) {return a * dot(a, b) / norm(a);}
P perp(L l, P p) {return l.first + proj(vec(l), p - l.first);}
P refl(L l, P p) {return perp(l, p) * (D)2 - p;}
 
// テ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool iLL(L a, L b) {return !eq(det(vec(a), vec(b)), 0);}
bool eqL(L a, L b) {return !iLL(a, b) && eq(det(vec(a), b.first - a.first), 0);}
bool iLS(L a, L b) {return sig(det(vec(a), b.first - a.first)) * sig(det(vec(a), b.second - a.first)) <= 0;}
bool iLSs(L a, L b) {return sig(det(vec(a), b.first - a.first)) * sig(det(vec(a), b.second - a.first)) < 0;}
bool iSS(L a, L b) {
  int cwa = ccw(a, b.first) | ccw(a, b.second);
  int cwb = ccw(b, a.first) | ccw(b, a.second);
  return ((cwa | cwb) & ON) || ((cwa & cwb) == (LEFT | RIGHT));
}
bool iSSs(L a, L b) {return ((ccw(a, b.first) | ccw(a, b.second)) & (ccw(b, a.first) | ccw(b, a.second))) == (LEFT | RIGHT);}

// テ、ツコツ、テァツつケ
P pLL(L a, L b) {return a.first + vec(a) * (det(vec(b), b.first - a.first) / det(vec(b), vec(a)));}

// ティツキツ敕ゥツ崢「
D dLP(L l, P x) {return abs(det(vec(l), x - l.first)) / abs(vec(l));}
D dSP(L s, P x) {
  if (sig(dot(vec(s), x - s.first)) <= 0) return abs(x - s.first);
  if (sig(dot(-vec(s), x - s.second)) <= 0) return abs(x - s.second);
  return dLP(s, x);
}
D dLL(L a, L b) {return iLL(a, b) ? 0 : dLP(a, b.first);}
D dLS(L a, L b) {return iLS(a, b) ? 0 : min(dLP(a, b.first), dLP(a, b.second));}
D dSS(L a, L b) {return iSS(a, b) ? 0 : min(min(dSP(a, b.first), dSP(a, b.second)), min(dSP(b, a.first), dSP(b, a.second)));}

// テヲツッツ氾ィツシツεゥツ鳴「テヲツ閉ー
namespace std {
  bool operator<(P a, P b) {return eq(a.X, b.X) ? a.Y < b.Y : a.X < b.X;}
}
L sortBase;
bool lessArg(P a, P b) {
  D ang1 = ang(sortBase.first, sortBase.second, a);
  D ang2 = ang(sortBase.first, sortBase.second, b);
  return eq(ang1, ang2) ? norm(a) > norm(b) : ang1 < ang2;
}

// テ・ツ??
struct C{
  P c; D r;
  C() {}
  C(P c, D r) : c(c), r(r) {}
};

// 2テ・ツ??」ツ?ョテ、ツスツ催ァツスツョテゥツ鳴「テ、ツソツ?
enum RELATION{SAME = 1, CONTAIN = 2, OVER = 4, NO_CROSS = 8, ONE_CROSS = 16, ONE_CONTAIN_CROSS = 32, ONE_OVER_CROSS = 64, TWO_CROSS = 128};
int cRel(C c1, C c2) {
  D d = abs(c1.c - c2.c);
  if (near(c1.c, c2.c) && eq(c1.r, c2.r)) return SAME;
  if (sig(d - (c1.r - c2.r)) < 0) return OVER;
  if (sig(d - (c2.r - c1.r)) < 0) return CONTAIN;
  if (eq(d, c1.r - c2.r)) return ONE_OVER_CROSS;
  if (eq(d, c2.r - c1.r)) return ONE_CONTAIN_CROSS;
  if (eq(d, c1.r + c2.r)) return ONE_CROSS;
  if (sig(d - (c1.r + c2.r)) > 0) return NO_CROSS;
  return TWO_CROSS;
}

// テァツつケテ」ツ?古・ツ??」ツ?ォテ・ツ青ォテ」ツ?セテ」ツつ古」ツつ凝」ツ??
bool iCP(C c, P p) {return sig(abs(p - c.c) - c.r) <= 0;}
// テ、ツコツ、テ・ツキツョテ・ツ按、テ・ツョツ?
bool iCL(C c, L l) {return sig(c.r - dLP(l, c.c)) >= 0;}
// テ・ツ??」ツ?ィテ、ツコツ、テ・ツキツョテ」ツ?崚」ツ?堙・ツョツ古・ツ?ィテ」ツ?ォテ・ツ青ォテ」ツ?セテ」ツつ古」ツ?ヲテ」ツつづィツ可ッテ」ツ??・ツ?エテ・ツ青暗」ツ?ッ&&テ、ツサツ・テゥツ卍催」ツつ津・ツ可甘ゥツ卍、
bool iCS(C c, L s) {return iCL(c, s) && sig(c.r - max(abs(s.first - c.c), abs(s.second - c.c))) <= 0;}
bool iCC(C a, C b) {return sig(abs(a.c - b.c) - abs(a.r - b.r) >= 0) && sig(abs(a.c - b.c) - a.r - b.r) <= 0;}

// テ、ツコツ、テァツつケ
pair<P, P> pCC(C a, C b) {
  D d = abs(b.c - a.c);
  D x = (d * d + a.r * a.r - b.r * b.r) / (2 * d);
  P e = (b.c - a.c) / abs(b.c - a.c), w = e * P(0, 1) * sqrt(max(a.r * a.r - x * x, (D)0));
  return make_pair(a.c + e * x - w, a.c + e * x + w);
}
pair<P, P> pCL(C c, L l) {
  P h = perp(l, c.c);
  P e = vec(l) / abs(vec(l)) * sqrt(max(c.r * c.r - norm(h - c.c), (D)0));
  return make_pair(h - e, h + e);
}

// ティツァツ津」ツ?ョテ・ツ??・ツ、ツ姪・ツ按、テ・ツョツ?ティツァツ誕bテ」ツ?ョテ・ツ??ゥツδィテ」ツ?ォテ」ツ?づ」ツつ古」ツ?ーテヲツュツ」テ」ツ??ィツセツコテ、ツクツ甘」ツ?ッ0テ」ツ??・ツ、ツ姪ゥツδィテ」ツ?ッティツイツ?
int sAP(P a, P b, P c) {return sig(det(a, c)) - sig(det(b, c)) - sig(det(a, b));}

// テ・ツ、ツ堙ィツァツ津・ツスツ「テ」ツ?ョテゥツ敖「テァツゥツ?
D aPol(Pol vp) {
  D ret = 0;
  rep (i, vp.size()) ret += det(vp[i], vp[(i + 1) % vp.size()]);
  return abs(ret / 2);
}

// テ、ツクツ嘉ィツァツ津・ツスツ「テ」ツ?ョテゥツ敖「テァツゥツ?
D aTri(D a, D b, D c){
  D s = (a + b + c) / 2;
  return sqrt(max(s * (s - a) * (s - b) * (s - c), (D)0));
}

// テ・ツ、ツ堙ィツァツ津・ツスツ「テ」ツ?ョテ・ツ??・ツ、ツ姪・ツ按、テ・ツョツ?テ・ツ??ゥツδィ:1テ」ツ??・ツ堕ィテ、ツクツ?0テ」ツ??・ツ、ツ姪ゥツδィ:-1
int sGP(Pol pol, P p) {
  int side = -1;
  rep (i, pol.size()) {
    P p0 = pol[i] - p, p1 = pol[(i + 1) % pol.size()] - p;
    if (sig(det(p0, p1)) == 0 && sig(dot(p0, p1)) <= 0) return 0;
    if (p0.Y > p1.Y) swap(p0, p1);
    if (sig(p0.Y) <= 0 && 0 < sig(p1.Y) && sig(det(p0, p1)) > 0) side *= -1;
  }
  return side;
}

// テ・ツ?クテ・ツ個?
Pol convexHull(Pol p) {
  int m = 0;
  vector<P> q(p.size() * 2);
  sort(p.begin(), p.end());
  for (int i = 0; i < int(p.size()); q[m++] = p[i++]) for (; m > 1 && sig(det(q[m - 1] - q[m - 2], p[i] - q[m - 2])) <= 0; --m);
  for (int i = p.size() - 2, r = m; i >= 0; q[m++] = p[i--]) for (; m > r && sig(det(q[m - 1] - q[m - 2], p[i] - q[m - 2])) <= 0; --m);
  q.resize(m - 1);
  return q;
}

// テ・ツ?クテ・ツ個?」ツつォテ」ツδε」ツδ?
Pol convexCut(Pol p, L l) {
  vector<P> q;
  rep (i, p.size()) {
    if (ccw(l, p[i]) & (LEFT | BACK | ON | FRONT)) q.push_back(p[i]);
    if (iLSs(l, L(p[i], p[(i + 1) % p.size()]))) q.push_back(pLL(l, L(p[i], p[(i + 1) % p.size()])));
  }
  return q;
}

// テァツキツ堙・ツ按?」ツつ津」ツδ榲」ツδシテ」ツつクテ」ツ?凖」ツつ?
vector<L> merge(vector<L> s) {
  rep (i, s.size()) if (s[i].second < s[i].first) swap(s[i].first, s[i].second);
  sort(s.begin(), s.end());
  rep (i, s.size()) rep (j, i) if (iSS(s[i], s[j]) && !iLL(s[i], s[j])) {
    s[j].second = max(s[i].second, s[j].second);
    s.erase(s.begin() + i--);
    break;
  }
  return s;
}

// テァツキツ堙・ツ按?」ツつ「テ」ツδャテ」ツδウテ」ツつクテ」ツδ。テ」ツδウテ」ツδ?テゥツ堋」テ」ツ?ョテァツつケテ」ツ?クテ」ツ?ョティツセツコテ」ツ?ョテ」ツ?ソテ」ツつ津ヲツ個?」ツ?、
pair<vector<P>, vector<vector<int> > > sArr(vector<L> s) {
  s = merge(s);
  vector<P> vp;
  rep (i, s.size()) {
    vp.push_back(s[i].first);
    vp.push_back(s[i].second);
  }
  rep (i, s.size()) rep (j, i) if (iSS(s[i], s[j])) vp.push_back(pLL(s[i], s[j]));
  sort(vp.begin(), vp.end());
  vp.erase(unique(vp.begin(), vp.end(), near), vp.end());
  vector<vector<int> > g(vp.size());
  rep (i, s.size()) {
    vector<pair<D, int> > v;
    rep (j, vp.size()) if (ccw(s[i], vp[j]) == ON) v.push_back(make_pair(norm(vp[j] - s[i].first), j));
    sort(v.begin(), v.end());
    rep (j, v.size() - 1) {
      g[v[j + 1].second].push_back(v[j].second);
      g[v[j].second].push_back(v[j + 1].second);
    }
  }
  return make_pair(vp, g);
}

int main() {
  int n;
  cin >> n;
  Pol pol;
  rep (i, n) {
    P p;
    cin >> p.X >> p.Y;
    pol.push_back(p);
  }
  Pol con = convexHull(pol);
  if (con.size() < 3u) {
    cout << 0 << endl;
    return 0;
  }
  D res = 0;
  if (con.size() == 3u) {
    rep (i, n) {
      if (near(pol[i], con[0])) continue;
      if (near(pol[i], con[1])) continue;
      if (near(pol[i], con[2])) continue;
      rep (j, 3) {
	Pol sq;
	sq.push_back(con[j]);
	sq.push_back(con[(j + 1) % 3]);
	sq.push_back(con[(j + 2) % 3]);
	sq.push_back(pol[i]);
	res = max(res, aPol(sq));
      }
    }
    printf("%.1Lf\n", res);
    return 0;
  }
  n = con.size();
  rep (i, n) {
    int right = (i + 1) % n;
    int left = (i + 3) % n;
    rep (j, n - 1) {
      if (j <= 1) continue;
      L l(con[i], con[(i + j) % n]);
      while (dLP(l, con[right]) < dLP(l, con[(right + 1) % n])) right = (right + 1) % n;
      while (dLP(l, con[left]) < dLP(l, con[(left + 1) % n])) left = (left + 1) % n;
      res = max(res, abs(vec(l)) * (dLP(l, con[left]) + dLP(l, con[right])) / (D)2);
    }
  }
  printf("%.1Lf\n", res);
  return 0;
}
accuracy: 1
time_ms: 1230
memory_kb: 1496
final_rank: 4