QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#275755#7906. Almost ConvexMonohydroxidesWA 15ms3648kbC++205.0kb2023-12-05 00:19:492023-12-05 00:19:51

Judging History

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

  • [2023-12-05 00:19:51]
  • 评测
  • 测评结果:WA
  • 用时:15ms
  • 内存:3648kb
  • [2023-12-05 00:19:49]
  • 提交

answer

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;
using db = long double;

db eps = 1e-6;
db pi = acos(-1);

int sign(db a) {
    return a < -eps ? -1 : a > eps;
}

int cmp(db a, db b) {
    return sign(a - b);
}

struct Points {
    db x, y;
    
    Points(db _x = 0., db _y = 0.) : x(_x), y(_y) {}
    
    int operator<(const Points &rhs) const {
        int c = cmp(x, rhs.x);
        if (c) {
            return c == -1;
        }
        return cmp(y, rhs.y) == -1;
    }
};

Points operator+(Points a, Points b) {
    return Points(a.x + b.x, a.y + b.y);
}

Points operator-(Points a, Points b) {
    return Points(a.x - b.x, a.y - b.y);
}

db dot(Points a, Points b) {
    return a.x * b.x + a.y * b.y;
}

db Cross(Points a, Points b) {
    return a.x * b.y - a.y * b.x;
}

db len(Points a) {
    return sqrt(dot(a, a));
}

Points rotate(Points p, db angle) {
    return Points(p.x * cos(angle) - p.y * sin(angle), p.x * sin(angle) + p.y * cos(angle));
}

db Angle(Points a, Points b) {
    return acos(dot(a, b) / len(a) / len(b));
}

int quad(Points a) {
    return sign(a.y) == 1 || (sign(a.y) == 0 && sign(a.x) >= 0);
}

db Cross(Points p1, Points p2, Points p3) {
    return ((p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y));
}

int crossOp(Points p1, Points p2, Points p3) {
    return sign(Cross(p1, p2, p3));
}

bool isMiddle(db a, db m, db b) {
    return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}

bool isMiddle(Points a, Points m, Points b) {
    return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}

bool OnSeg(Points p1, Points p2, Points q) {
    return crossOp(p1, p2, q) == 0 && isMiddle(p1, q, p2);
}

vector<Points> convex_hell(vector<Points> &pts) {
    sort(pts.begin(), pts.end());
    int n = pts.size(), m = 0;
    vector<Points> ch;
    for (int i = 0; i < n; i++) {
        while (m > 1 && Cross(ch[m - 1] - ch[m - 2], pts[i] - ch[m - 2]) <= 0) {
            ch.pop_back();
            m--;
        }
        ch.push_back(pts[i]);
        m++;
    }
    int k = m;
    for (int i = n - 2; i >= 0; i--) {
        while (m > k && Cross(ch[m - 1] - ch[m - 2], pts[i] - ch[m - 2]) <= 0) {
            ch.pop_back();
            m--;
        }
        ch.push_back(pts[i]);
        m++;
    }
    if (n > 1) {
        ch.pop_back();
        m--;
    }
    return ch;
}

int pointsInPoly(vector<Points> &p, Points a) {
    int n = p.size(), ret = 0;
    for (int i = 0; i < n; i++) {
        Points u = p[i], v = p[(i + 1) % n];
        if (OnSeg(u, v, a)) {
            assert(0);
            return 1;
        }
        if (cmp(u.y, v.y) <= 0) {
            swap(u, v);
        }
        if (cmp(a.y, u.y) > 0 || cmp(a.y, v.y) <= 0) {
            continue;
        }
        ret ^= crossOp(a, u, v) > 0;
    }
    return ret * 2;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    vector<Points> pts;
    for (int i = 1; i <= n; i++) {
        int x, y;
        cin >> x >> y;
        pts.push_back(Points(double(x), double(y)));
    }
    auto ch = convex_hell(pts);
    vector<Points> notOnConvVec;
    map<Points, bool> onConv;
    for (int i = 0; i < ch.size(); i++) {
        onConv[ch[i]] = 1;
    }
    for (int i = 0; i < pts.size(); i++) {
        if (!onConv.count(pts[i])) {
            notOnConvVec.push_back(pts[i]);
        }
    }
    if (notOnConvVec.size() == 0) {
        cout << 1 << "\n";
        return 0;
    }
    int ans = 1;
    auto process = [&](vector<Points>& pts, Points a, Points b) {
        db angle = Angle(Points(1.0, 0.0), b - a);
        for (int i = 0; i < pts.size(); i++) {
            pts[i] = pts[i] - a;
            pts[i] = rotate(pts[i], 2 * pi - angle);
        }
        sort(pts.begin(), pts.end(), [](Points a, Points b) {
            int qa = quad(a), qb = quad(b);
            if (qa != qb) {
                return qa < qb;
            } else {
                return sign(Cross(a, b)) > 0;
            }
        });
        for (int i = 0; i < pts.size(); i++) {
            pts[i] = rotate(pts[i], angle);
            pts[i] = pts[i] + a;
        }
    };
    for (int i = 0; i < ch.size(); i++) {
        process(notOnConvVec, ch[i], ch[(i + 1) % ch.size()]);
        vector<Points> tmp;
        tmp.push_back(ch[i]);
        tmp.push_back(ch[(i + 1) % ch.size()]);
        tmp.push_back(notOnConvVec[0]);
        ans++;
        for (int j = 1; j < notOnConvVec.size(); j++) {
            auto las = tmp.back();
            tmp.pop_back();
            tmp.push_back(notOnConvVec[j]);
            if (!(pointsInPoly(tmp, las) >= 1)) {
                ans++;
                tmp.pop_back();
                tmp.push_back(notOnConvVec[j]);
            } else {
                tmp.pop_back();
                tmp.push_back(las);
            }
        }
    }
    cout << ans << "\n";
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3496kb

input:

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

output:

9

result:

ok 1 number(s): "9"

Test #2:

score: 0
Accepted
time: 0ms
memory: 3456kb

input:

5
4 0
0 0
2 1
3 3
3 1

output:

5

result:

ok 1 number(s): "5"

Test #3:

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

input:

3
0 0
3 0
0 3

output:

1

result:

ok 1 number(s): "1"

Test #4:

score: 0
Accepted
time: 0ms
memory: 3512kb

input:

6
0 0
3 0
3 2
0 2
1 1
2 1

output:

7

result:

ok 1 number(s): "7"

Test #5:

score: 0
Accepted
time: 0ms
memory: 3448kb

input:

4
0 0
0 3
3 0
3 3

output:

1

result:

ok 1 number(s): "1"

Test #6:

score: -100
Wrong Answer
time: 15ms
memory: 3648kb

input:

2000
86166 617851
383354 -277127
844986 386868
-577988 453392
-341125 -386775
-543914 -210860
-429613 606701
-343534 893727
841399 339305
446761 -327040
-218558 -907983
787284 361823
950395 287044
-351577 -843823
-198755 138512
-306560 -483261
-487474 -857400
885637 -240518
-297576 603522
-748283 33...

output:

787

result:

wrong answer 1st numbers differ - expected: '718', found: '787'