QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#65880#4226. Cookie CutterSortingRE 1ms3636kbC++5.0kb2022-12-04 07:07:052022-12-04 07:07:07

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-12-04 07:07:07]
  • 评测
  • 测评结果:RE
  • 用时:1ms
  • 内存:3636kb
  • [2022-12-04 07:07:05]
  • 提交

answer

#include <bits/stdc++.h>

using namespace std;

const int N = 1e4 + 3;
const int M = 3000 + 3;

typedef long long ll;
typedef long double ld;

const ld EPS = 1e-7;

#define all(x) (x).begin(), (x).end()

template<class T>
struct Point {
    typedef Point P;
    T x, y;
    Point(){}

    Point(T x, T y): x(x), y(y){}
    bool operator==(P p){
        return p.x == x && p.y == y;
    }
    T dist2() const{
        return x * x + y * y;
    }
    ld dist() const {
        return sqrt(x * x + y * y);
    }
    P operator*(T coeff){
        return {x * coeff, y * coeff};
    }
    P operator/(T coeff){
        return {x / coeff, y / coeff};
    }
    P operator+(P p){
        return {x + p.x, y + p.y};
    }
    P operator-(P p){
        return {x - p.x, y - p.y};
    }
    T cross(P p){
        return x * p.y - y * p.x;
    }
    T cross(P a, P b){
        return (*this - a).cross(*this - b);
    }
    T dot(P p) const {
        return x * p.x + y * p.y;
    }
    friend bool operator<(const Point &l, const Point &r){
        return tuple{l.x, l.y} < tuple{r.x, r.y};
    }
};

struct Angle{
    ld x, y, t;
    Angle(ld x, ld y): x(x), y(y){}
    int half() const{
        assert(x || y);
        return y < 0 || (y == 0 && x < 0);
    }
};
bool operator<(Angle a, Angle b){
    return make_tuple(a.t, a.half(), a.y*(ll)b.x) < 
           make_tuple(b.t, b.half(), a.x*(ll)b.y);
}

int n, m;
Point<ll> p[M];

template<class P>
pair<int, P> lineInter(P s1, P e1, P s2, P e2){
    auto d = (e1 - s1).cross(e2 - s2);
    if(d == 0)
        return pair{-(s1.cross(e1, s2) == 0), P{(ld)0, (ld)0}};
    auto p = s2.cross(e1, e2), q = s2.cross(e2, s1);
    return {1, (s1 * p + e1 * q) / d};
}

ld segDist(Point<ld> &s, Point<ld> &e, Point<ld> &p){
    if(s == e) return (p - s).dist();
    ld d = (s - e).dist2();
    ld t = min(d, max((ld).0, (p - s).dot(e-s)));
    return ((p-s)*d-(e-s)*t).dist()/d;
}

template<class T>
T polygonArea2(vector<Point<T>> &v){
    T a = v.back().cross(v[0]);
    for(int i = 0; i < (int)v.size() - 1; ++i)
        a += v[i].cross(v[i + 1]);
    return a;
}

ld area_right(Point<ld> a, Point<ld> b){
    // cout << a.x << " " << a.y << " - " << b.x << " " << b.y << endl;

    vector<Point<ld>> corners{{0, 0}, {0, n}, {n, n}, {n, 0}};
    vector<Point<ld>> points;
    for(int i = 0; i < 4; ++i){
        int nxt = (i + 1) % 4;
        auto inters = lineInter(a, b, corners[i], corners[nxt]);
        if(!inters.first)
            continue;
        if(segDist(corners[i], corners[nxt], inters.second) <= EPS)
            points.push_back(inters.second);
    }

    for(int i = 0; i < 4; ++i)
        points.push_back(corners[i]);

    vector<Point<ld>> points2;
    for(auto p: points)
        if(a.cross(b, p) >= 0)
            points2.push_back(p);
    sort(all(points2));

    vector<Angle> v;
    for(auto p: points2){
        auto dp = p - points2[0];
        if(dp.dist() > EPS)
            v.push_back(Angle(dp.x, dp.y));
    }
    sort(all(v));

    vector<Point<ld>> points3;
    points3.push_back(points2[0]);
    for(auto ang: v){
        points3.push_back(Point<ld>{ang.x + points2[0].x, ang.y + points2[0].y});
    }

    // cout << "points3: " << endl;
    // for(auto [x, y]: points3)
        // cout << x << " " << y << endl;
    // cout << endl;

    // cout << polygonArea2(points3) / 2 << " wtf guys" << endl;
    return abs(polygonArea2(points3)) / 2;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m;
    for(int i = 0; i < m; ++i)
        cin >> p[i].x >> p[i].y;

    ld ans = 0;
    for(int i = 0; i < m; ++i){
        // cout << i << " i" << endl;
        vector<Point<ld>> corners{{0, 0}, {0, n}, {n, n}, {n, 0}};
        for(auto corner: corners){
            ans = max(ans, (ld)1/m - area_right(Point<ld>{p[i].x, p[i].y}, corner) / (ld)(n * n));
            ans = max(ans, (ld)1/m - area_right(corner, Point<ld>{p[i].x, p[i].y}) / (ld)(n * n));
        }
    }

    // cout << ans << " ans" << endl;

    for(int i = 0; i < n; ++i){
        vector<Angle> v;
        for(int j = 0; j < n; ++j){
            if(i == j) continue;
            v.push_back(Angle(p[j].x - p[i].x, p[j].y - p[i].y));
        }
        sort(all(v));
        int j = 0, ptr = 0;
        for(; j < n - 1; ++j){
            // cout << i << " " << j << " " << ptr << endl;
            while((ptr + 1) % (n - 1) != j && Point<ld>{(ld)0,(ld)0}.cross(Point<ld>{v[j].x, v[j].y}, Point<ld>{v[(ptr + 1) % (n - 1)].x, v[(ptr + 1) % (n - 1)].y}) >= 0){
                ++ptr;
                ptr %= n - 1;
            }

            int cnt = ptr - j + 1;
            if(cnt <= 0)
                cnt += n - 1;
            ans = max(ans, (long double)(cnt + 1) / (long double)m - area_right(Point<ld>{p[i].x, p[i].y}, Point<ld>{v[j].x + p[i].x, v[j].y + p[i].y}) / (ld)((ld)n * n));

            if(ptr == j)
                ++ptr;
        }
    }

    cout << fixed << setprecision(12) << ans << "\n";
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

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

input:

5 8
1 1
1 2
1 3
2 1
3 1
3 4
4 1
4 2

output:

0.375000000000

result:

ok found '0.3750000', expected '0.3750000', error '0.0000000'

Test #2:

score: -100
Runtime Error

input:

10000 2916
93 93
93 278
93 463
93 649
93 834
93 1019
93 1204
93 1389
93 1574
93 1760
93 1945
93 2130
93 2315
93 2500
93 2685
93 2871
93 3056
93 3241
93 3426
93 3611
93 3796
93 3982
93 4167
93 4352
93 4537
93 4722
93 4907
93 5093
93 5278
93 5463
93 5648
93 5833
93 6018
93 6204
93 6389
93 6574
93 6759...

output:


result: