QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#124282#3139. Largest QuadrilateralGoatGirl98WA 2ms3236kbC++146.3kb2023-07-14 16:32:122023-07-14 16:32:13

Judging History

This is the latest submission verdict.

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-07-14 16:32:13]
  • Judged
  • Verdict: WA
  • Time: 2ms
  • Memory: 3236kb
  • [2023-07-14 16:32:12]
  • Submitted

answer

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
const double INF = 1145141919810114514.0;
const double eps = 1e-9;
int sgn(double x)
{

    if(fabs(x) > eps)
        return x > 0 ? 1 : -1;
    else
        return 0;
}
struct point
{
    double x, y, idx;
    point(double _x = 0.0, double _y = 0.0) : x(_x), y(_y), idx(0) {}
    point operator-(const point& o) const { return point(x - o.x, y - o.y); }
    // cross product of vector 
    double operator^(const point& o) const { return x * o.y - y * o.x; }
    double dis2(const point& o) const { return (x - o.x) * (x - o.x) + (y - o.y) * (y - o.y); }
    double dis(const point& o) const { return sqrt(dis2(o)); }
    bool operator<(const point& o) const { return sgn(x - o.x) ? (sgn(x - o.x) < 0) : (sgn(y - o.y) < 0); }
    bool operator==(const point& o) const { return sgn(x - o.x) == 0 && sgn(y - o.y) == 0; }
};
struct line
{
    point s, e;
    line() {}
    line(point _s, point _e) : s(_s), e(_e) {}
    // segment only
    double len() const { return s.dis(e); }
    double dis_point_to_line(const point& p) const { return fabs((p - s) ^ (e - s)) / len(); }
};
// andrew
vector<point> get_convex(vector<point>& points)
{
    int n = (int)points.size();
    // sorted before calling this
    // sort(points.begin(), points.end());
    vector<int> stk;
    vector<bool> used(n);
    stk.push_back(0);
    // upper convex
    for (int i = 1; i < n; ++i)
    {
        while (stk.size() >= 2 && sgn((points[stk[stk.size() - 1]] - points[stk[stk.size() - 2]]) ^ (points[i] - points[stk[stk.size() - 1]])) <= 0)
            used[stk.back()] = false, stk.pop_back();
        used[i] = true, stk.push_back(i);
    }
    // stk.back() == n - 1
    // lower convex
    int upper_size = stk.size();
    for (int i = n - 2; i >= 0; --i)
    {
        if (used[i])
            continue;
        while (stk.size() > upper_size && sgn((points[stk[stk.size() - 1]] - points[stk[stk.size() - 2]]) ^ (points[i] - points[stk[stk.size() - 1]])) <= 0)
            used[stk.back()] = false, stk.pop_back();
        used[i] = true, stk.push_back(i);
    }
    // stk.back() == stk[0]
    vector<point> ret;
    for (int i = 0; i < stk.size(); ++i)
        ret.push_back(points[stk[i]]);
    return ret;
}
double largest_quadrilateral(vector<point>& points)
{
    // int n = points.size();
    sort(points.begin(), points.end());
   // points.erase(unique(points.begin(), points.end()), points.end());
    int n = points.size();
    for (int i = 0; i < n; ++i)
        points[i].idx = i;
    vector<point> hull = get_convex(points);
    int m = hull.size() - 1;
    if (m == 2) // collinear points
        return 0.0;
    else if (m == 3) // big triangle(hull) - small triangle(inside)
    {
        double triangle_area_double = fabs((hull[2] - hull[1]) ^ (hull[1] - hull[0]));
        double cut_triangle_double = INF;
        for (int i = 0; i < n; ++i)
        {
            if (points[i].idx == hull[0].idx || points[i].idx == hull[1].idx || points[i].idx == hull[2].idx)
                continue;
            double cut_double_1 = fabs((hull[0] - points[i]) ^ (hull[1] - points[i]));
            double cut_double_2 = fabs((hull[1] - points[i]) ^ (hull[2] - points[i]));
            double cut_double_3 = fabs((hull[2] - points[i]) ^ (hull[0] - points[i]));
            cut_triangle_double = min(min(cut_triangle_double, cut_double_1), min(cut_double_2, cut_double_3));
        }
        if (sgn(INF - cut_triangle_double) == 0)
            return 0.0;
        else
            return (triangle_area_double - cut_triangle_double) / 2.0;
    }
    else // rotating cliper (2 groups)
    {
        double ans_double = 0.0;
        // Antipodal point-point (i, j) and (x, y)
        int i = 0, j = 1, x = 0, y = 1;
        for (; i < m; ++i)
        {
            while (1)
            {
                int flag = sgn((hull[(i + 1) % m] - hull[i]) ^ (hull[(j + 1) % m] - hull[j]));
                if (flag <= 0) // (i, j) is antipodal point-point
                {
                    line diagonal = line(hull[i], hull[j]);
                    while ((x + 1) % m != j && sgn(diagonal.dis_point_to_line(hull[x]) - diagonal.dis_point_to_line(hull[(x + 1) % m])) < 0)
                        x = (x + 1) % m;
                    while ((y + 1) % m != i && sgn(diagonal.dis_point_to_line(hull[y]) - diagonal.dis_point_to_line(hull[(y + 1) % m])) < 0)
                        y = (y + 1) % m;
                    ans_double = max(ans_double, diagonal.len() * (diagonal.dis_point_to_line(hull[x]) + diagonal.dis_point_to_line(hull[y])));
                    
                    // corner case : (i, (i + 1) % m) parallel with (j, (j + 1) % m)
                    if (flag == 0)
                    {
                        j = (j + 1) % m;
                        diagonal = line(hull[i], hull[j]);
                        while ((x + 1) % m != j && sgn(diagonal.dis_point_to_line(hull[x]) - diagonal.dis_point_to_line(hull[(x + 1) % m])) <= 0)
                            x = (x + 1) % m;
                        while ((y + 1) % m != i && sgn(diagonal.dis_point_to_line(hull[y]) - diagonal.dis_point_to_line(hull[(y + 1) % m])) <= 0)
                            y = (y + 1) % m;
                        ans_double = max(ans_double, diagonal.len() * (diagonal.dis_point_to_line(hull[x]) + diagonal.dis_point_to_line(hull[y])));
                        j = (j + m - 1) % m;
                    }
                    break;
                }
                // rad : i < x < j < y
                if (y == j)
                    y = (y + 1) % m;
                j = (j + 1) % m;
            }
            if (x == i)
                x = (x + 1) % m;
        }
        return ans_double / 2.0;
    }
}
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        int n;
        scanf("%d", &n);
        vector<point> points(n);
        for (int i = 0; i < n; ++i)
            scanf("%lf%lf", &points[i].x, &points[i].y);
        double ans = largest_quadrilateral(points);
        if (sgn(ans - (long long)(ans + eps)) == 0)
            printf("%lld\n", (long long)(ans + eps));
        else
            printf("%lld.5\n", (long long)(ans + eps));
    }
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 3100kb

input:

3
5
0 0
1 0
3 1
1 2
0 1
4
0 0
4 0
0 4
1 1
4
0 0
1 1
2 2
1 1

output:

3
6
0

result:

ok 3 lines

Test #2:

score: 0
Accepted
time: 1ms
memory: 3136kb

input:

1
4
0 0
1 0
0 1
3 2

output:

2.5

result:

ok single line: '2.5'

Test #3:

score: 0
Accepted
time: 1ms
memory: 3008kb

input:

3
4
0 0
0 0
0 0
0 0
5
0 0
1 0
3 1
1 2
0 1
4
0 0
4 0
0 4
1 1

output:

0
3
6

result:

ok 3 lines

Test #4:

score: 0
Accepted
time: 1ms
memory: 3184kb

input:

3
4
0 0
1 1
2 2
1 1
5
0 0
3 3
1 1
4 4
2 2
6
0 0
0 4
4 0
0 0
1 1
1 2

output:

0
0
8

result:

ok 3 lines

Test #5:

score: -100
Wrong Answer
time: 2ms
memory: 3236kb

input:

3
6
0 0
8 8
7 9
6 9
5 8
0 99
29
999891293 708205
369022896 771
993004062 999827531
929592437 29458
994968624 999539287
569046020 1943
2200 986643253
11189 5792636
712825 999917190
2482686 272282
43058 665660
10373878 31825
508452623 112
3304 269412577
43817590 3789
999996618 957802194
999902626 9749...

output:

388
996775018731291776
965005706567704576

result:

wrong answer 2nd lines differ - expected: '996775018731291724.5', found: '996775018731291776'